Какие различные хранилища доступны / используются программой во время выполнения? - PullRequest
2 голосов
/ 22 августа 2009

Как правило, когда вы запускаете какую-либо программу, во время выполнения, какие ей доступны различные хранилища и для чего они используются? Я понимаю стек и кучу. Кроме того, я знаю, что типы значений помещаются в стек, а типы ссылок - в кучу. Но я также сталкивался с такими терминами, как счетчик программ, указатель инструкций.

Что они означают?

BOUNTY: Ниже приведены несколько действительно хороших ответов. Я ищу что-то более подробное. Кое-что, что не заставит меня прочитать несколько глав из книги COA. Определенные блоги / видео / объяснения оценены.

Ответы [ 4 ]

3 голосов
/ 22 августа 2009

Основными типами памяти на любом языке высокого уровня являются те два, которые вы уже определили: стек и куча.

Нет предела тому, что вы можете поместить в одну или другую; разница в том, как и когда эта память выделяется. Пространство стека выделяется при вызове функции, и все сразу, поэтому вы не можете выделить какое-либо новое пространство стека изнутри функции, и как только функция вернет, эта память освобождается. Куча пространства, с другой стороны, вы распределяете сами, когда хотите и в любом количестве, которое хотите.

Есть, конечно, другие куски памяти, которые используются внутри, которые вы обычно не трогаете. Например, «программный счетчик» и «указатель команд» - это одно и то же: одно слово памяти, которое отслеживает, какая команда в вашей программе будет следующей. Каждый раз, когда процессор выполняет команду, счетчик программ переходит к следующему.

После выполнения вызова функции счетчик программы сохраняется в стеке вместе с вашими локальными переменными, поэтому при вызове вызываемой функции вызывающая функция будет знать, где она "остановилась".

3 голосов
/ 22 августа 2009

Я думаю, что вы задаете два разных, но связанных вопроса. Во-первых, как организованы данные для моей программы? Разные архитектуры делают это по-разному, но в основном программа состоит из 3 (или 4, в зависимости от того, как их считать): data (куча и статические глобальные данные), стек (локальный и вызов функции / данные возврата) и текст (код).

Во-вторых, как компьютер запускает мою программу? Это действительно вопрос о компьютерной архитектуре и операционной системе семантике. Программный счетчик или указатель инструкций, как правило, является одним из многих регистров в ЦП, которые используются при запуске вашей программы. Он отслеживает расположение в памяти выполняемой в данный момент инструкции. Другие включают указатель стека (или фрейма) (текущее местоположение стекового фрейма выполняемой функции), слово состояния программы (информация о результатах текущей инструкции) и регистры данных.

Существует намного больше того, что нужно для запуска вашей программы, и я только просмотрел поверхностные биты аппаратного обеспечения низкого уровня, но вопросы, которые вы поднимаете, действительно требуют учебника для полного понимания. Для более тщательного изучения я бы предложил взять копию Организация и архитектура компьютеров в местном книжном магазине или библиотеке.

2 голосов
/ 01 сентября 2009

Существует множество различных концептуальных хранилищ данных в вычислительной машине, а также много различных фактических хранилищ памяти в различных конкретных реализациях вычислительной машины.

В начале была лента, и много ее.

В качестве примера приведем концептуальную машину Тьюринга , в которой хранилищем являются ЛЕНТА, ТАБЛИЦА и ГОСУДАРСТВЕННЫЙ РЕГИСТР.

Это все различные формы хранения:

Лента изменчива и неограниченна. ТАБЛИЦА может быть изменяемой (хотя часто нет), но ограничена регистр состояния является изменяемым и ограниченным. ПОЛОЖЕНИЕ ГОЛОВКИ простое, но очень важное в том смысле, что оно допускает свободное движение, ограниченное только самой лентой и логикой в ​​ТАБЛИЦЕ.

Далее вы можете видеть, что в идеализированных моделях TABLE и STATE REGISTER считаются «быстрыми» для доступа к любой записи внутри (для доступа / изменения требуется некоторое постоянное время), тогда как доступ к некоторому произвольному элементу ленты зависит от расстояния от текущего местоположения на ленте до места, где находятся данные.

Это позволяет провести значительный анализ различных аспектов вычислительной системы и принципиально моделирует идею о том, что в системе неограниченный источник данных неизбежно будет демонстрировать нелинейное поведение с точки зрения стоимости доступа (поскольку представление о том, как добраться до данных, само будет расти по мере роста хранимых данных.

Модель памяти машины Тьюринга была не столь далека от реальных физических машин в раннюю эпоху мэйнфрейм-компьютеров, при этом большинство постоянных хранилищ основывались на (по общему признанию конечных) лентах, а STATE REGISTER был основан на небольшом простом пуле память 'в машине с равными затратами на доступ к любой записи. Многие из первых компьютеров не имеют «программ» в том смысле, в каком вы или я думаем. Вместо этого они могли изменить свой TABLE (часто буквально вручную), а затем все дальнейшее поведение было исправлено. Это было отделение ДАННЫХ от ИНСТРУКЦИИ.

Поскольку современные компьютеры изменили эту связь, одно из первых формальных описаний вычислительных устройств стало все более и более далеким.

Случайно считается не вредным

Большинство современных машин основано на Von Neumann Architecture . Они явно помещают инструкции и данные в один и тот же «пул» адресуемой памяти. Их начальный TABLE просто достаточен, чтобы начать чтение инструкций из памяти, которая на основе данных может решить, какие инструкции использовать в будущем.

Для поддержания STATE было разработано много разных способов, некоторые хранили все это в основном пуле памяти, другие создавали определенные области памяти либо как произвольно адресуемые именованные «регистры» отдельно от основной памяти, либо как «стеки», часто реализуемые занимает часть основной памяти.

Они не являются эксклюзивными, у многих есть концепция стека и регистров, некоторые предоставляют отдельную память для стека, другие нет и помещают ее в основную память. Несколько машин либо обязали (или поощряли в соответствии с соглашением), что определенные регистры ссылаются на концептуальный стек, общим именем для конкретного регистра во многих архитектурах является указатель стека (SP).

Почти все имели концепцию определенного места хранения (обычно это регистр), которая указала следующую команду для выполнения. Изменение этого значения (от базового дополнительного к последнему значению), обеспечивающее основные средства для компьютера общего назначения, таким образом, указатель инструкций (или IP, как стало известно это специальное местоположение) представляет нечто похожее на расположение ГОЛОВКИ в машине Тьюринга (за исключением того, что она повторяет инструкции, а не данные). Переместив все данные в произвольно адресуемую форму, концепция ленты данных была удалена из «памяти».

Вместо этого то, что когда-то было основной памятью компьютера, вместо этого отводится памяти устройства ввода-вывода. Память, но больше не то, что большинство людей называют памятью в том смысле, в каком мы ее используем сейчас.

В ранних компьютерах такого типа регистры и ОЗУ обычно работали с одинаковой «скоростью», хотя было необходимо переместить данные из ОЗУ в регистр и обратно, это была простая инструкция, как и любая другая.

По мере увеличения скорости, с которой могли работать логические блоки, скорость, с которой (все больше и больше) доступ к ОЗУ, уменьшалась в относительном выражении. Частично это объяснялось тем, что быстро стало легче отделять логические блоки от блоков памяти с точки зрения затрат.

Поскольку такие регистры были «специальным» хранилищем, которое было «близко» к логическим блокам, обычно работало с той же скоростью, что и логические блоки. Основная память стала «еще дальше» от логических элементов и стала стоить больше циклов доступа.

Сообщения в узком месте

Код должен был быть разработан для выполнения таким образом, чтобы уменьшить количество раз, когда данные должны были копироваться в регистр, с которым нужно работать, а затем копироваться обратно в основную память. Компьютерные дизайнеры поняли, что в целом определенный «стиль» на самом деле довольно распространен во многих программах: доступ к меньшей части основной памяти осуществляется гораздо чаще, чем к другим частям.
Способность компилятора / человека эффективно использовать регистры для управления этим была ограничена. Попытка организовать вычисления для эффективного использования этого более быстрого хранилища потребовала сложного определения зависимостей. Добавление регистров, поскольку каждое из них было «особым именем», было непростым решением, поскольку добавление большего количества данных включало перекодирование каждого приложения и принудительное переписывание для каждого «обновления».

Было понято, что было возможно поместить некоторую часть основной памяти «ближе» к логике, возможно, не так близко, как регистры, но гораздо ближе, чем основная память. Поскольку не было экономически эффективным (и во многих случаях невозможно) закрыть всю такую ​​память, это должно было бы стать «окном» в основную память. Ранние дизайнеры понимали, что помещение этого в управление программисту приведет ко многим из тех же проблем, связанных с фиксированным количеством регистров. Поэтому они пытались использовать эту более близкую память таким образом, чтобы прозрачно для программиста и программы, за исключением тех случаев, когда это влияло на производительность .

Кэш-память родилась, поэтому временная локальность была создана для более быстрых компьютеров без изменений кода.

Были опробованы различные формы (и многие сосуществуют даже сейчас), например, эксклюзивные и инклюзивные (теперь что-то может быть в двух местах одновременно). Также было рассчитано, что если память имеет тенденцию иметь временную локальность, она также стремится к пространственной локализации, поскольку такие данные могут находиться в кэше, даже если вы еще не запрашивали ее умозрительно .

Некоторые разделяли кеш между данными и инструкциями, другие - нет, но почти все компьютеры перешли на кеш.

Все черепахи внизу

Вскоре память стала намного медленнее, чем кеш, поэтому стоило поместить более медленный, но больший кеш между основной памятью и небольшим кешем. Уровень 1 и уровень 2 кэш были созданы, и даже более того.

Чем больше, тем быстрее, сильнее

Когда мы стали быстрее, стало ясно, что на самом деле большая часть кода может выполняться одновременно с помощью конвейерной передачи или независимого параллельного выполнения. При этом, запуская несколько скрытых логических блоков из простого представления, как это видно программисту и компилятору, требовалось больше «скрытых» регистров для учета множества в операциях полета. Переименование регистров было разработано таким образом, чтобы можно было использовать несколько копий одного и того же «регистра», которые используются на одной в разных исполнительных блоках, чтобы скрыть изменения в одной от другой.
«Где» была сохранена часть состояния, стало еще сложнее, хотя, к счастью, все еще скрыто от большинства программистов.

В то же время это происходило, и мы начали испытывать проблемы, связанные с тем, чтобы сделать один процессор быстрее, в основном из-за того, что кэш пытался уменьшить узкое место. Поскольку такой транзисторный бюджет начал расходоваться на другие совершенно независимые разделы логики, и надеялись, что программисты начнут писать код, ожидающий несколько единиц, а не одну.

Это приводит к некоторым проблемам. Ранее все «скрытые» способы уменьшения задержки памяти никогда не имели значения для программиста. Однако теперь модель «разделяемой» основной памяти этого нового мирового порядка SMP сработала против вас. «адрес» в паре памяти может быть во многих местах одновременно, на самом деле он может иметь несколько разных значений в этих местах.

Теперь стало важно не только , где была память, но и насколько стабильно это было. был ли кусок памяти в кеше или нет, и модели программирования пришлось менять. В этот момент «Модель памяти» архитектуры стала очень важной (и очень сложной).

Разделяй и властвуй

Поскольку это сложное взаимодействие «скрытого» непрозрачного искажения памяти плохо взаимодействовало с новой моделью нескольких отдельных блоков, начали появляться различные возможные решения.

Очевидно, что если для запроса значения не требуется кэширование, это упрощает протоколы когерентности кэша.

Другой, менее очевидный (и все еще неясный относительно его пригодности), прекратит иметь этот большой общий пул памяти и вместо этого предоставит каждому блоку свой собственный кусок памяти с явным взаимодействием между ними и старой основной памятью. .

Это разделение памяти становится еще более сложным, так как устройства, ранее не относящиеся к тому же классу, что и универсальные центральные процессоры, изогнуты в эта модель .

Не забывай о будущем

Это, конечно, только начало большего количества изменений, в будущем вы можете обнаружить, что память будет описываться с еще большей сложностью как кубитов или как что-то совершенно неизвестное.

2 голосов
/ 22 августа 2009

Счетчик программ и указатель команд - это одно и то же. По сути, указатель инструкций отслеживает, какую команду выполняет процессор. Ваша программа будет находиться в отдельной части памяти, иногда называемой сегментом кода. Указатель инструкции указывает на местоположение в этом сегменте.

Стоит отметить, что счетчик программ не хранится в ОЗУ (это будет слишком медленно) Это регистр процессора. Программный счетчик сохраняется в стеке только при вызове функции. Затем, когда программа возвращается из вызова функции, возвращаемые значения выводятся из стека и счетчик программ восстанавливается.

Более подробное объяснение см. Здесь .

...