Иерархия памяти

    Введение:

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

    Объектом исследования в данной курсовой работе есть память ЭВМ. Одним из основных факторов увеличения производительности ЭВМ есть использование многоуровневой организации памяти, что позволяет увеличить скорость обработки данных за счет работы верхних уровней иерархии памяти. Предметом исследования в данной курсовой работе есть иерархия памяти ЭВМ.

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

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

    Многие программисты не учитывают многоуровневость памяти при программировании. Этот подход работает, пока, приложение не столкнется с падением производительности из-за нехватки производительности подсистемы памяти (memory wall). При исправлении кода (Рефакторинг) необходимо учесть наличие и особенность работы верхних уровней иерархии памяти для достижения наивысшей производительности.

    Иерархия  памяти современных компьютеров  строится на нескольких уровнях, причем более высокий уровень меньше по объему, быстрее и имеет большую  стоимость в пересчете на байт, чем более низкий уровень. Уровни иерархии взаимосвязаны: все данные на одном уровне могут быть также найдены на более низком уровне, и все данные на этом более низком уровне могут быть найдены на следующем нижележащем уровне и так далее, пока мы не достигнем основания иерархии.

    Поэтому, ставим перед собой задачи:

  • принцип работы регистровой памяти;
  • принцип работы кэш-памяти;
  • устройство оперативной памяти;
  • изучение разновидностей внешних запоминающих устройств.
 
 
 
 

 

  1. Внутренняя память процессора
    1. Регистры процессора

    Регистр процессора — сверхбыстрая оперативная память (СОЗУ) внутри процессора, предназначенная прежде всего для хранения промежуточных результатов вычисления — РОН (регистр общего назначения) или содержащая данные, необходимые для работы процессора — смещения базовых таблиц, уровни доступа и т. д. (специальные регистры).

    Регистр представляет собой цифровую электронную схему, служащую для временного хранения двоичных чисел. В процессоре имеется значительное количество регистров, большая часть которых используется самим процессором и недоступна программисту(например, при выборке из памяти очередной команды она помещается в регистр команд, и программист обратиться к этому регистру не может). Имеются также регистры, которые в принципе программно доступны, но обращение к ним осуществляется из программ операционной системы (например, управляющие регистры и теневые регистры дескрипторов сегментов). Этими регистрами пользуются в основном разработчики операционных систем. Существуют также так называемые регистры общего назначения(РОН), представляющие собой часть регистров процессора, использующихся без ограничения в арифметических операциях, но имеющие определенные ограничения, например в строковых. РОН, не характерные для эпохи мейнфреймов типа IBM/370 стали популярными в микропроцессорах архитектуры X86i8085, i8086 и последующих.

    Доступ к значениям, хранящимся в регистрах, как правило, в несколько раз быстрее, чем доступ к ячейкам оперативной памяти (даже если кеш-память содержит нужные данные), но объём оперативной памяти намного превосходит суммарный объём регистров (объём среднего модуля оперативной памяти сегодня составляет 1-4 Гб, суммарная «ёмкость» регистров общего назначения/данных для процессора Intel 80x86 16 битов * 4 = 64 бита (8 байт)).

    Регистром называется функциональный узел, осуществляющий приём, хранение и передачу информации. Регистры состоят из группы триггеров, обычно D. По типу приёма и выдачи информации различают 2 типа регистров:

  • С последовательным приёмом и выдачей информации — сдвиговые регистры.
  • С параллельным приёмом и выдачей информации — параллельные регистры.

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

    По назначению регистры различаются на:

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

    Регистровый файл (register file) — модуль микропроцессора (CPU), содержащий в себе реализацию регистров процессора. Современные регистровый файлы, используемые в СБИС обычно реализованы как многопортовый массив быстрой статической памяти SRAM. Такие массивы SRAM отличаются явным разделением портов чтения и записи, тогда как классическая многопортовая SRAM обычно позволяет как читать так и записывать через любой порт.

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

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

    Регистровые файлы содержат по одной строке слов на каждый порт, по одной битовой линии на бит слова для каждого порта чтения и по две битовые линии на бит слова для каждого порта записи. Также каждая ячейка должна иметь входы питания Vdd и земли Vss. Следовательно, с увеличением количества портов площадь, требуемая под разводку растет квадратично, а площадь, занимаемая транзисторами — линейно. В какой-то момент, возможно, будет более оптимально по площади или по задержкам иметь несколько регистровых файлов с дублирующейся информацией и половиной портов чтения в каждом, чем один большой регистровый файл сразу со всеми портами чтения.

    Например, регистровый файл в целочисленном АЛУ микропроцессора MIPS R8000, имеющий 9 портов чтения, 4 порта записи, содержащий 32 64хбитных регистра и реализованный на техпроцессе 0.7 мкм, имеет такие размеры, что хорошо различим невооруженным глазом даже на расстоянии порядка 30 см.

    Рисунок 1. Типичный регистровый файл с 3 портами, в котором возможно одновременное чтение из 2 регистров и запись в 1 регистр, состоит из ячеек похожих на изображенную.

    1. Кэш процессора
      1. Принцип работы

    Ядро микросхемы статической оперативной памяти (SRAM - Static Random Access Memory) представляет собой совокупность триггеров - логических устройств, имеющих два устойчивых состояния, одно из которых условно соответствует логическому нулю, а другое - логической единице. Другими словами, каждый триггер хранит один бит информации, - ровно столько же, сколько и ячейка динамической памяти

    Между тем, триггер как минимум по двум позициям обыгрывает конденсатор: а) состояния триггера устойчивы и при наличии питания могут сохраняться бесконечно долго, в то время как конденсатор требует периодической регенерации; б) триггер, обладая мизерной инертностью, без проблем работает на частотах вплоть до нескольких ГГц, тогда как конденсаторы "сваливаются" уже на 75-100 МГц.

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

    Устройство триггера

    В основе всех триггеров лежит кольцо из двух логических элементов "НЕ" (инверторов), соединенных по типу "защелки" (см. рис. 2). Рассмотрим, как он работает. Если подать на линию Q сигнал, соответствующий единице, то, пройдя сквозь элемент D.D1 он обратится в ноль. Но, поступив на вход следующего элемента, - D.D2 - этот ноль вновь превратится в единицу. Поскольку, выход элемента D.D2 подключен ко входу элемента D.D1, то даже после исчезновения сигнала с линии Q, он будет поддерживать себя самостоятельно, т.е. триггер перейдет в устойчивое состояние. Образно это можно уподобить дракону, кусающему себя за хвост.

    Естественно, если на линию Q подать сигнал, соответствующий логическому нулю, - все будет происходить точно так же, но наоборот!

    

    Рисунок 2. Устройство простейшего триггера (слева). Образно это можно представить драконом, кусающим свой хвост

    Устройство элемента "НЕ" (инвертора)

    Как устроен элемент "НЕ"? На этот вопрос нельзя ответить однозначно. В зависимости от имеющейся у нас элементарной базы, конечная реализация варьируется в очень широких пределах. Ниже в качестве примера приведена принципиальная схема простейшего инвертора, сконструированного из двух последовательно соединенных комплементарных /* взаимно дополняемых */ CMOS-транзисторов - p- и n- канального (см. рис. 3). Если на затворы подается нулевой уровень, то открывается только p-канал, а n-канал остается разомкнутым. В результате, на выходе мы имеем питающее напряжение (т. е. высокий уровень). Напротив, если на затворы подается высокий уровень, размыкается n-канал, а p-канал - замыкается. Выход оказывается закорочен на массу и на нем устанавливается нулевое напряжение (т. е. низкий уровень).

    

    Рисунок 3. Устройство элемента НЕ (инвертора)

    Устройство матрицы статической памяти

    Подобно ячейкам динамической памяти, триггеры объединяются в единую матрицу, состоящую из строк (row) и столбцов (column), последние из которых так же называются битами (bit).

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

    

    Рисунок 4. Устройство 6-транзистроной одно-портовой ячейки SRAM-памяти

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

    Этого ограничения лишена многопортовая память. Каждая ячейка многопортовой памяти содержит один-единственный триггер, но имеет несколько комплектов управляющих транзисторов, каждый из которых подключен к "своим" линиям ROW и BIT, благодаря чему различные ячейки матрицы могут обрабатываться независимо. Такой подход намного более прогрессивен, чем деление памяти на банки. Ведь, в последнем случае параллелизм достигается лишь при обращении к ячейкам различных банков, что не всегда выполнимо, а много портовая память допускает одновременную обработку любых ячеек, избавляя программиста от необходимости вникать в особенности ее архитектуры. (Замечание: печально, но кэш-память x86-процессор не истинно многопортовая, а состоит из восьми одно-портовых матриц, подключенных к двух портовой интерфейсной обвязке)

    Наиболее часто встречается двух - портовая память, устройство ячейки которой изображено на рис. 5. (внимание! это совсем не та память которая, в частности, применяется в кэше первого уровня микропроцессоров Intel Pentium). Нетрудно подсчитать, что для создания одной ячейки двух - портовой памяти расходуется аж восемь транзисторов. Пусть емкость кэш-памяти составляет 32 Кб, тогда только на одно ядро уйдет свыше двух миллионов транзисторов!

    

    Рисунок 5. Устройство 8-транзистроной двух портовой ячейки SRAM-памяти

    Устройство интерфейсной обвязки

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

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

    Если статическая память выполнена в виде самостоятельной микросхемы, а не располагается непосредственно на кристалле процессора, линии ее входа зачастую объединяют с линиями выхода, и требуемый режим работы приходится определять по состоянию специального вывода WE (Write Enable). Высокое состояние вывода WE готовит микросхему к чтению данных, а низкое - к записи. Статическая память, размещенную на одном кристалле вместе с процессором, обычно не мультиплексирует, и в этом случае содержимое одной ячейки можно читать параллельно с записью другой (линии входа и выхода ведь раздельные).

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

    

    Рисунок 6. Устройство типовой микросхемы SRAM-памяти

    Временные диаграммы чтения/записи

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

    Цикл чтения

    Цикл чтения начинается со сброса сигнала CS (Chip Select - Выбор Чипа) в низкое состояние, давая понять тем самым микросхеме, что чип "выбран" и сейчас с ним будут работать (и работать будут, и прорабатывать!).

    К тому моменту, когда сигнал стабилизируется, на адресных линиях должен находиться готовый к употреблению адрес ячейки (т.е. номер строки и номер столбца), а сигнал WE должен быть переведен в высокое состояние (соответствующее операции чтения ячейки). Уровень сигнала OE (Output Enable - разрешение вывода) не играет никакой роли, т.к. на выходе пока ничего не содержится, точнее выходные линии находятся в, так называемом, высоко импедансом состоянии.

    Спустя некоторое время (tAddress Access), определяемое быстродействием управляющей логики и быстротечностью переходных процессорах в инверторах, на линиях выхода появляются долгожданные данные, которые вплоть до окончания рабочего цикла (tCycle) могут быть непосредственно считаны. Обычно время доступа к ячейке статической памяти не превышает 1 - 2 нс., а зачастую бывает и меньше того!

    Цикл записи

    Цикл записи происходит в обратном порядке. Сначала мы выставляем на шину адрес записываемой ячейки и одновременно с этим сбрасываем сигнал WE в низкое состояние. Затем, дождавшись, когда наш адрес декодируется, усилиться и поступит на соответствующие битовые линии, сбрасываем CS в низкий уровень, приказывая микросхеме подать сигнал высокого уровня на требуемую линию row. Защелка, удерживающая триггер, откроется и в зависимости от состоянии bit-линии, триггер переключится в то или иное состояние.

    

    Рисунок 7. Временные диаграммы чтения/записи асинхронной статической памяти 

    
      1. Ассоциативность

      Ассоциативность является компромиссом. Если бы существовало 10 мест, в которые алгоритм вытеснения мог бы отобразить место в памяти, тогда проверка наличия этого места в кэше потребовала бы просмотра 10 записей в кэше. Проверка большего числа записей требует больше энергии, площади чипа, и, потенциально, времени. С другой стороны, кэши с высокой ассоциативностью подвержены меньшему количеству промахов (см ниже конфликтующие промахи), и, значит, процессор тратит меньше времени на чтения из медленной основной памяти. Существует эмпирическое наблюдение, что удвоение ассоциативности (от прямого отображения к 2-хканальной, или от 2-х к 4-х канальной) имеет примерно такое же влияние на интенсивность попаданий (hit rate), что и удвоение размера кэша. Увеличение ассоциативности свыше 4х каналов приносит меньший эффект для уменьшения количества промахов (miss rate), и, обычно, производится по другим причинам, например из-за пересечения виртуальных адресов.

    В порядке увеличения (ухудшения) длительности проверки на попадание и уменьшения (улучшения) miss rate,

  • Кэш прямого отображения, direct mapped cache — наилучшее время попадания, и, соответственно, лучший вариант для больших кэшей
  • 2-х канальный множественно-ассоциативный кэш,
  • 4-х канальный множественно-ассоциативный кэш,
  • Полностью ассоциативный кэш, — наилучший (самый низкий) процент промахов (miss rate), и лучший вариант при чрезвычайно высоких затратах при промахе (miss penalty)
      1. Типы  статической памяти

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

    Асинхронная статическая память

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

    Синхронная статическая память

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

    Конвейерная статическая память

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

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

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

    
      1. Специализированные кэши

    Суперскалярные ЦПУ осуществляют доступ к памяти из нескольких этапов конвейера: чтение инструкции (instruction fetch), трансляция виртуальных адресов в физические, чтение данных (data fetch). Очевидным решением является использование различных физических кэшей для каждого из этих случаев, чтобы не было борьбы за доступ к одному из физических ресурсов с разных стадий конвейера. Таким образом, наличие конвейера обычно приводит к наличию по крайней мере трёх раздельных кэшей: кэш инструкций, кэш трансляций TLB и кэш данных, каждый из которых специализирован на своей задаче.

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

    Victim cache — это небольшой специализированный кэш, хранящий те кэш-линии, которые были недавно вытеснены из основного кэша микропроцессора при их замещении. Данный кэш располагается между основным кэшем и его refill path. Обычно кэш жертв является полностью ассоциативным и служит для уменьшения количества конфликтных промахов (conflict miss). Многие часто используемые программы не требуют полного ассоциативного отображения для всех попыток доступа к памяти. По статистике, только небольшая доля обращений к памяти потребует высокой степени ассоциативности. Именно для таких обращений служит кэш жертв, предоставляющий высокую ассоциативность для подобных редких запросов. Был внедрен Norman Jouppi в 1990.

Иерархия памяти