Существует множество различных концептуальных хранилищ данных в вычислительной машине, а также много различных фактических хранилищ памяти в различных конкретных реализациях вычислительной машины.
В начале была лента, и много ее.
В качестве примера приведем концептуальную машину Тьюринга , в которой хранилищем являются ЛЕНТА, ТАБЛИЦА и ГОСУДАРСТВЕННЫЙ РЕГИСТР.
Это все различные формы хранения:
Лента изменчива и неограниченна.
ТАБЛИЦА может быть изменяемой (хотя часто нет), но ограничена
регистр состояния является изменяемым и ограниченным.
ПОЛОЖЕНИЕ ГОЛОВКИ простое, но очень важное в том смысле, что оно допускает свободное движение, ограниченное только самой лентой и логикой в ТАБЛИЦЕ.
Далее вы можете видеть, что в идеализированных моделях TABLE и STATE REGISTER считаются «быстрыми» для доступа к любой записи внутри (для доступа / изменения требуется некоторое постоянное время), тогда как доступ к некоторому произвольному элементу ленты зависит от расстояния от текущего местоположения на ленте до места, где находятся данные.
Это позволяет провести значительный анализ различных аспектов вычислительной системы и принципиально моделирует идею о том, что в системе неограниченный источник данных неизбежно будет демонстрировать нелинейное поведение с точки зрения стоимости доступа (поскольку представление о том, как добраться до данных, само будет расти по мере роста хранимых данных.
Модель памяти машины Тьюринга была не столь далека от реальных физических машин в раннюю эпоху мэйнфрейм-компьютеров, при этом большинство постоянных хранилищ основывались на (по общему признанию конечных) лентах, а STATE REGISTER был основан на небольшом простом пуле память 'в машине с равными затратами на доступ к любой записи. Многие из первых компьютеров не имеют «программ» в том смысле, в каком вы или я думаем. Вместо этого они могли изменить свой TABLE (часто буквально вручную), а затем все дальнейшее поведение было исправлено. Это было отделение ДАННЫХ от ИНСТРУКЦИИ.
Поскольку современные компьютеры изменили эту связь, одно из первых формальных описаний вычислительных устройств стало все более и более далеким.
Случайно считается не вредным
Большинство современных машин основано на Von Neumann Architecture . Они явно помещают инструкции и данные в один и тот же «пул» адресуемой памяти. Их начальный TABLE просто достаточен, чтобы начать чтение инструкций из памяти, которая на основе данных может решить, какие инструкции использовать в будущем.
Для поддержания STATE было разработано много разных способов, некоторые хранили все это в основном пуле памяти, другие создавали определенные области памяти либо как произвольно адресуемые именованные «регистры» отдельно от основной памяти, либо как «стеки», часто реализуемые занимает часть основной памяти.
Они не являются эксклюзивными, у многих есть концепция стека и регистров, некоторые предоставляют отдельную память для стека, другие нет и помещают ее в основную память. Несколько машин либо обязали (или поощряли в соответствии с соглашением), что определенные регистры ссылаются на концептуальный стек, общим именем для конкретного регистра во многих архитектурах является указатель стека (SP).
Почти все имели концепцию определенного места хранения (обычно это регистр), которая указала следующую команду для выполнения. Изменение этого значения (от базового дополнительного к последнему значению), обеспечивающее основные средства для компьютера общего назначения, таким образом, указатель инструкций (или IP, как стало известно это специальное местоположение) представляет нечто похожее на расположение ГОЛОВКИ в машине Тьюринга (за исключением того, что она повторяет инструкции, а не данные). Переместив все данные в произвольно адресуемую форму, концепция ленты данных была удалена из «памяти».
Вместо этого то, что когда-то было основной памятью компьютера, вместо этого отводится памяти устройства ввода-вывода. Память, но больше не то, что большинство людей называют памятью в том смысле, в каком мы ее используем сейчас.
В ранних компьютерах такого типа регистры и ОЗУ обычно работали с одинаковой «скоростью», хотя было необходимо переместить данные из ОЗУ в регистр и обратно, это была простая инструкция, как и любая другая.
По мере увеличения скорости, с которой могли работать логические блоки, скорость, с которой (все больше и больше) доступ к ОЗУ, уменьшалась в относительном выражении. Частично это объяснялось тем, что быстро стало легче отделять логические блоки от блоков памяти с точки зрения затрат.
Поскольку такие регистры были «специальным» хранилищем, которое было «близко» к логическим блокам, обычно работало с той же скоростью, что и логические блоки. Основная память стала «еще дальше» от логических элементов и стала стоить больше циклов доступа.
Сообщения в узком месте
Код должен был быть разработан для выполнения таким образом, чтобы уменьшить количество раз, когда данные должны были копироваться в регистр, с которым нужно работать, а затем копироваться обратно в основную память. Компьютерные дизайнеры поняли, что в целом определенный «стиль» на самом деле довольно распространен во многих программах: доступ к меньшей части основной памяти осуществляется гораздо чаще, чем к другим частям.
Способность компилятора / человека эффективно использовать регистры для управления этим была ограничена. Попытка организовать вычисления для эффективного использования этого более быстрого хранилища потребовала сложного определения зависимостей. Добавление регистров, поскольку каждое из них было «особым именем», было непростым решением, поскольку добавление большего количества данных включало перекодирование каждого приложения и принудительное переписывание для каждого «обновления».
Было понято, что было возможно поместить некоторую часть основной памяти «ближе» к логике, возможно, не так близко, как регистры, но гораздо ближе, чем основная память. Поскольку не было экономически эффективным (и во многих случаях невозможно) закрыть всю такую память, это должно было бы стать «окном» в основную память. Ранние дизайнеры понимали, что помещение этого в управление программисту приведет ко многим из тех же проблем, связанных с фиксированным количеством регистров. Поэтому они пытались использовать эту более близкую память таким образом, чтобы прозрачно для программиста и программы, за исключением тех случаев, когда это влияло на производительность .
Кэш-память родилась, поэтому временная локальность была создана для более быстрых компьютеров без изменений кода.
Были опробованы различные формы (и многие сосуществуют даже сейчас), например, эксклюзивные и инклюзивные (теперь что-то может быть в двух местах одновременно). Также было рассчитано, что если память имеет тенденцию иметь временную локальность, она также стремится к пространственной локализации, поскольку такие данные могут находиться в кэше, даже если вы еще не запрашивали ее умозрительно .
Некоторые разделяли кеш между данными и инструкциями, другие - нет, но почти все компьютеры перешли на кеш.
Все черепахи внизу
Вскоре память стала намного медленнее, чем кеш, поэтому стоило поместить более медленный, но больший кеш между основной памятью и небольшим кешем. Уровень 1 и уровень 2 кэш были созданы, и даже более того.
Чем больше, тем быстрее, сильнее
Когда мы стали быстрее, стало ясно, что на самом деле большая часть кода может выполняться одновременно с помощью конвейерной передачи или независимого параллельного выполнения. При этом, запуская несколько скрытых логических блоков из простого представления, как это видно программисту и компилятору, требовалось больше «скрытых» регистров для учета множества в операциях полета. Переименование регистров было разработано таким образом, чтобы можно было использовать несколько копий одного и того же «регистра», которые используются на одной в разных исполнительных блоках, чтобы скрыть изменения в одной от другой.
«Где» была сохранена часть состояния, стало еще сложнее, хотя, к счастью, все еще скрыто от большинства программистов.
В то же время это происходило, и мы начали испытывать проблемы, связанные с тем, чтобы сделать один процессор быстрее, в основном из-за того, что кэш пытался уменьшить узкое место. Поскольку такой транзисторный бюджет начал расходоваться на другие совершенно независимые разделы логики, и надеялись, что программисты начнут писать код, ожидающий несколько единиц, а не одну.
Это приводит к некоторым проблемам. Ранее все «скрытые» способы уменьшения задержки памяти никогда не имели значения для программиста. Однако теперь модель «разделяемой» основной памяти этого нового мирового порядка SMP сработала против вас. «адрес» в паре памяти может быть во многих местах одновременно, на самом деле он может иметь несколько разных значений в этих местах.
Теперь стало важно не только , где была память, но и насколько стабильно это было. был ли кусок памяти в кеше или нет, и модели программирования пришлось менять. В этот момент «Модель памяти» архитектуры стала очень важной (и очень сложной).
Разделяй и властвуй
Поскольку это сложное взаимодействие «скрытого» непрозрачного искажения памяти плохо взаимодействовало с новой моделью нескольких отдельных блоков, начали появляться различные возможные решения.
Очевидно, что если для запроса значения не требуется кэширование, это упрощает протоколы когерентности кэша.
Другой, менее очевидный (и все еще неясный относительно его пригодности), прекратит иметь этот большой общий пул памяти и вместо этого предоставит каждому блоку свой собственный кусок памяти с явным взаимодействием между ними и старой основной памятью. .
Это разделение памяти становится еще более сложным, так как устройства, ранее не относящиеся к тому же классу, что и универсальные центральные процессоры, изогнуты в эта модель .
Не забывай о будущем
Это, конечно, только начало большего количества изменений, в будущем вы можете обнаружить, что память будет описываться с еще большей сложностью как кубитов или как что-то совершенно неизвестное.