Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Высокопроизводительные системы и подсистемы памяти. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
11.08.2026
Размер:
503 Кб
Скачать

Когда процессору нужно обратиться в память для чтения или записи данных, он сначала проверяет, доступна ли их копия в кэшпамяти. В случае успеха проверки процессор производит операцию, используя кэш-память, что значительно быстрее использования более медленной основной памяти. Современные высокопроизводительные системы имеют 2 – 3 уровня иерархии кэш-памяти. Первые два уровня (L1 и L2) находятся на кристалле, кэш-память L3 может находиться как на кристалле, так и быть внешней памятью. В этом случае это, как правило, отдельный кристалл, устанавливаемый в одном корпусе с микропроцессором (может быть 3D сборка). Емкость кэш-памяти с каждым годом растет по мере улучшения технологических норм, что позволяет поднимать производительность вычислительных систем. Емкость современной кэш-памяти 1-го уровня составляет, как правило, от 32 до 64 Кбайт, емкость кэш-памяти 2-го уровня может достигать нескольких единиц мегабайт, емкость кэш-памяти 3-го уровня превышает емкость кэш-памяти 2-го уровня в несколько раз. Кэш-память организуется как массив кэш-линий (блоков фиксированного размера), каждая из которых имеет свой порядковый номер. В каждой линии кэшпамяти сохраняется фиксированного размера блок данных, идущих подряд в оперативной памяти. Этот блок данных называется размером кэш-линии. Кэш-линия обычно содержит четыре слова, т.е. при записи в кэш-память происходит запись всех четырех подряд идущих слов – запись кэш-линии. Для архитектуры x86 размер кэш-линии составляет 64 байта. Такая организация кэш-памяти связана еще и со спецификой организации динамической памяти, когда чтение/запись первого слова происходит за несколько тактов (до 15 для наиболее быстродействующей памяти), а последующие три слова – по одному такту на слово. Нецелесообразно терять возможность быстрого извлечения рядом находящихся слов, тем более, что обычно данные, необходимые для последовательного выполнения программы, располагаются в памяти также последовательно. Таким образом, процесс обмена данными оперативной и кэш-памяти происходит не отдельными байтами, а пакетами, состоящими из нескольких подряд идущих слов. Основные отличия в организации кэш-памяти 1-го уровня – в разделении ее на память данных и инструкций (гарвардская архитектура), и тип доступа, как

21

правило – это ассоциативная память (fully associative cache), когда каждая кэш-линия (блок данных) может располагаться в любом месте, или множественно-ассоциативная память.

Кэш-память 3-го уровня делается как память с прямым отображением (direct mapped), когда каждая линия кэш-памяти может располагаться только на одном месте. Кэш-память 2-го уровня по сложности и скорости доступа занимает промежуточный уровень. Доступ в кэш-память 2-го уровня множественно-ассоциативный с меньшим, чем у кэш-памяти 1-го уровня, числом уровней ассоциативности. В этом случае блок может располагаться на ограниченном множестве мест в кэш (n-way set associative), число мест определяет уровень ассоциативности.

Ассоциативность кэш-памяти является непосредственным показателем ее логической сегментации: сколько каналов, столько и сегментов. Кэш-память с n-канальной ассоциативностью предполагает, что информация, размещенная по некоторому адресу в оперативной памяти, может находиться в n местах (строках) этой кэшпамяти. В пределах любого отдельно взятого сегмента только одна строка может кэшировать информацию, находящуюся по некоторому адресу в оперативной памяти. Отсюда следует, что если адрес известен, то контроллеру во всем сегменте следует обработать только одну строку. Таким образом, при получении запроса на чтение или запись контроллер опросит нужные строки во всех имеющихся сегментах на предмет наличия (cache hit) или отсутствия (cache miss) информации, соответствующей полученному адресу. В случае попадания данные будут извлечены из кэш-памяти; если все сегменты ответили негативно на запрос о чтении информации, то он будет перенаправлен к контроллеру кэш-памяти более низкого уровня, и так далее вплоть до контроллера оперативной памяти. Понятно, чем больше уровень ассоциативности, тем сложнее и дольше осуществляется поиск требуемого слова в кэш-памяти, но тем и эффективнее становится кэш-память за счет возможности размещения в ней различных (не идущих подряд) частей данных и инструкций. Эффективность кэш-памяти определяется числом попаданий (hit rate) в нее при обращении процессора в память. Оптимизация уровня ассоциативности и размера кэш-памяти – важный фактор повышения производительности микропроцессора. Удвое-

22

ние ассоциативности от прямого отображения к 2-канальному имеет примерно такое же влияние на частоту попаданий, что и удвоение размера кэш-памяти. Увеличение ассоциативности свыше четырех каналов приносит меньший эффект, как правило, уровень ассоциативности не больше 8. Итак, механизм создания иерархической памяти заключается в расположении наверху наиболее быстродействующей, но небольшого размера памяти, а внизу – памяти большого объема с невысокой скоростью. Почему такой механизм эффективен? Это происходит из-за особенности расположения программ и данных в памяти, в среднем 90 % времени работы программы связано с доступом к 10 % адресного пространства этой программы, правило представляют в виде так называемого правила 90/10. В большинстве программ с высокой вероятностью адрес очередной команды программы либо следует непосредственно за адресом, по которому была считана текущая команда, либо расположен вблизи него. Такое расположение адресов называется пространственной локальностью программы. Обрабатываемые данные, как правило, структурированы, и такие структуры обычно хранятся в последовательных ячейках памяти. Данная особенность программ называется пространственной локальностью данных. Кроме того, программы содержат множество небольших циклов и подпрограмм. Это означает, что небольшие наборы команд могут многократно повторяться в течение некоторого интервала времени, т.е. имеет место временная локальность. Чем большее число раз повторяется подпрограмма, тем большей производительности можно достичь. Поэтому программу разумно представить в виде последовательно обрабатываемых частей. Помещая такие части программы в более быстродействующую память, можно существенно снизить общие задержки на обращение, поскольку команды и данные, один раз переданные из медленного ОЗУ в быстродействующую память, затем могут использоваться многократно. Соответственно среднее время доступа к ним в этом случае будет определяться уже быстрой памятью. На каждом уровне иерархии информация разбивается на блоки, которые и пересылаются между уровнями. При доступе к командам и данным, например, для их считывания, сначала производится поиск в памяти верхнего уровня. Факт обнаружения нужной информации называют попаданием

23

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

1.Коэффициент попаданий (hit rate) – отношение числа обращений к памяти, при которых произошло попадание, к общему числу обращений к ЗУ данного уровня иерархии.

2.Коэффициент промахов (miss rate) – отношение числа обращений к памяти, при которых имел место промах, к общему числу обращений к ЗУ данного уровня иерархии.

3.Время обращения при попадании (hit time) – время, необходимое для поиска нужной информации в памяти верхнего уровня, плюс время на фактическое считывание данных.

4.Время потери на промах (miss penalty) – время, требуемое для замены блока в памяти более высокого уровня на блок с нужными данными, расположенный в ЗУ следующего (более низкого) уровня.

4.3. Полностью ассоциативная кэш-память

Кэш-память характеризуется емкостью C (от англ. capacity), числом наборов S (от англ. set), длиной строки, иногда называемой размером блока b (от англ. block), количеством строк или блоков B и степенью ассоциативности N.

Полностью ассоциативная кэш-память (англ.: fully associative cache) имеет только один набор (S = 1), и данные могут оказаться в любой из B строк этого набора.

Схема полностью ассоциативной кэш-памяти представлена на рис. 4.2. В такой памяти любая строка ОЗУ может находиться в любом месте кэш-памяти в любой комбинации с другими строками.

Кэш-память состоит из памяти сохраняемых данных, инструкций (для кэш-памяти 1-го уровня это разные памяти) или адреса (в

24

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

Если при следующем обращении имеется попадание в кэшпамять, они будут считаны из кэш-памяти. Если нет (кэш-промах), обращение снова происходит к ОЗУ, и при этом одновременно заполняется очередная кэш-строка.

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

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

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

25

Тэг

Старшие разряды адреса процессора (тэг)

Кэш-память

 

 

Данные

Строка состояния

 

V M

=

 

 

=

 

 

 

 

1

 

Шина данных

 

V

M

=

 

 

=

 

 

Рис. 4.2. Структурная схема полностью ассоциативной кэш-памяти

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

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

26

Одним из наиболее эффективных является алгоритм замещения на основе наиболее давнего использования (LRU – Least Recently Used), при котором замещается та строка кэш-памяти, к которой дольше всего не было обращения. Проводившиеся исследования показали, что алгоритм LRU, который «смотрит» назад, работает достаточно хорошо в сравнении с оптимальным алгоритмом, «смотрящим» вперед.

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

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

Другой возможный алгоритм замещения – алгоритм, работающий по принципу «первый вошел, первый вышел» (FIFO – First In First Out). Здесь заменяется строка, дольше всего находившаяся в кэш-памяти. Алгоритм легко реализуется с помощью рассмотренной ранее очереди, с той лишь разницей, что после обращения к строке положение соответствующей ссылки в очереди не меняется.

Еще один алгоритм – замена наименее часто использовавшейся строки (LFU – Least Frequently Used). Заменяется та строка в кэшпамяти, к которой было меньше всего обращений. Реализовать его можно, связав каждую строку со счетчиком обращений, к содержимому которого после каждого обращения добавляется единица. Главным претендентом на замещение является строка, счетчик которой содержит наименьшее число.

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

27

сом, вне зависимости от того, имело место попадание или промах. Значение в счетчике определяет заменяемую строку.

Кроме тега и байтов данных в кэш-строке могут содержаться дополнительные служебные поля, среди которых в первую очередь следует отметить бит достоверности V (от valid – действительный, имеющий силу) и бит модификации M (от modify – изменять, модифицировать). При заполнении очередной кэш-строки V устанавливается в состояние «достоверно», а M – в состояние «не модифицировано». В случае, если в ходе выполнения программы содержимое данной строки было изменено, переключается бит M, сигнализируя о том, что при замене данной строки ее содержимое следует переписать в ОЗУ. Если по каким-либо причинам произошло изменение копии элемента данной строки, хранимого в другом месте (например, в ОЗУ), переключается бит V. При обращении к такой строке будет зафиксирован кэш-промах (несмотря на то, что тег совпадает), и обращение произойдет к основному ОЗУ. Кроме того, служебное поле может содержать биты, поддерживающие алгоритм LRU.

4.4. Индикаторы состояния строки

Помимо тэга и данных строка кэш-памяти содержит служебную информацию, описывающую ее состояние. На рис. 4.2 это строка состояния. Существует ряд действий, в результате которых информация в кэш-памяти становится недействительной. Соответственно, необходимо это состояние как-то обозначить. Возможно введение по одному биту действительности (validity bit) на каждую строку, описывающему ее состояние. Допустим, что строка считается действительной, если этот бит является высоким. Для повышения надежности из-за радиационных эффектов возможно добавление к биту действительности еще одного, хранящего его противоположное значение. Если при чтении обоих окажется, что они одинаковы, то соответствующая строка должна быть признана недействительной. Вероятность изменения обоими битами своих значений на противоположные очень мала. Для многопроцессорных систем необходим также бит модифицированности (modified bit), который указывает, является ли данная строка копией соответствующей

28

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

Третьим важным индикатором состояния строки кэш-памяти является бит общности (shared bit). Он показывает, имеются ли копии данной строки в кэш-памяти других процессоров. Если один из процессоров изменит свою копию, то другие процессоры должны быть поставлены в известность и предпринять действия по отношению к своим копиям. Существуют два метода синхронизации:

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

Создан ряд протоколов, позволяющих реализовать требуемые функции по работе с кэш-памятью. Наиболее популярным является

MESI (Modified, Exclusive, Shared, Invalid), реализующийся в соответствии со строкой состояния табл. 4.1.

Таблица 4.1

Строка состояния для протокола MESI

Состояние

M

V

 

 

 

 

 

 

Modified

1

0

 

 

 

 

 

 

Exclusive

0

1

 

 

 

 

 

 

Shared

1

1

 

 

 

 

 

 

Invalid

0

0

 

 

 

 

 

 

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

29

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

Допустим, в D-cache была загружена строка из оперативной памяти, и строка состояния получает значение Exclusive. При ее вытеснении другой строкой из D-cache в S-cache она сохраняет свой прежний статус. Когда она снова будет загружена в D-cache, ее состояние изменится на Shared, равно как и состояние оставшейся в S-cache копии. При изменении хранящегося в D-cache значения возможны два варианта: изменения будут направлены как в S- cache, так и в оперативную память, а состояния обеих строк сохранятся как Shared; изменения не будут никуда направляться, строка в S-cache будет помечена как Invalid, а изменяемая в D-cache примет статус Modified.

Существует несколько разновидностей протокола MESI: MSI

(Modified, Shared, Invalid), MOSI (Modified, Owned, Shared, Invalid), MOESI (Modified, Owned, Exclusive, Shared, Invalid) и MOWESI (Modified, Owned, Written, Exclusive, Shared, Invalid). Протокол

MOESI требует наличие уже трех разрядов для реализации состояний, а его основное преимущество заключается в ликвидации основного недостатка MESI, связанного с невозможностью хранения измененных строк в более чем одной кэш-памяти. Для этого введено новое состояние Owned, которое означает владение правами собственности на данную строку кэш-памяти, ее копий в других кэш-памятях и в оперативной памяти. Эта функция требует от данного ведущего устройства, реализующего состояние Owned (далее – ведущее устройство), обеспечить все мастера в системе верной информацией. Однако в этом случае усложняется логика, обеспечивающая состояние Modified. При каждом запросе каким-либо мастером информации из кэшируемого пространства оперативной памяти ведущее устройство должно запрос приостанавливать, затем генерировать запрос всем процессорам на предмет наличия соответствующей строки в их кэш-памяти. Если у одного

30

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]