
ЭВУ 2 семестр / Презентации ЭВУ в пдф / метода моховикова
.pdfПолитика WB позволяет уменьшить количество операций записи на шине основной памяти. Если блок памяти, в который должна производиться запись, отображен в кэше, то физическая запись сначала будет произведена в эту действительную строку кэша, которая отмечается как грязная (dirty), или модифицированная, т. е. требующая выгрузки в основную память. Только после этой выгрузки (записи в основную память) строка станет чистой
(clean), и ее можно будет использовать для кэширования других блоков без потери целостности данных. В основную память данные переписываются только целой строкой. Эта выгрузка контроллером может откладываться до наступления крайней необходимости (обращение к кэшированной памяти другим абонентом, замещение в кэше новыми данными) или выполняться в свободное время после модификации всей строки. При возникновении запро-
са к памяти выполняется просмотр кэша, и если запрашиваемых данных там нет, то запись выполняется только в основную память. В противном же слу-
чае запись производится только в кэш-память, при этом в описателе данных делается специальная отметка (признак модификации), которая указывает на то, что при вытеснении этих данных из кэша необходимо переписать их в ос-
новную память, чтобы актуализировать устаревшее содержимое основной памяти. Данный алгоритм сложнее в реализации, но существенно эффектив-
нее, чем WT. Поддержка системной платой кэширования с обратной записью требует обработки дополнительных интерфейсных сигналов для выгрузки модифицированных строк в основную память, если к этой области произво-
дится обращение со стороны таких контроллеров шины, как другие процес-
соры, графические адаптеры, контроллеры дисков, сетевые адаптеры и т. п.
13.3. Ассоциативность
Основополагающим принципом логического сегментирования является тот факт, что в пределах любого отдельно взятого сегмента только одна строка может кэшировать информацию, находящуюся по некоторому адресу в оперативной памяти. Отсюда следует, что если адрес известен, то контрол-
211
леру во всем сегменте следует обработать только одну строку. Таким обра-
зом, при получении запроса на чтение или запись контроллер опросит нуж-
ные строки во всех имеющихся сегментах на предмет наличия (cache hit) или отсутствия (cache miss) информации, соответствующей полученному адресу.
Либо все сегменты возвратят сигнал отсутствия, либо за исключением одно-
го, ответившего сигналом наличия. В случае положительного отзыва кон-
троллеру нет необходимости проводить какой-либо дальнейший анализ, дос-
таточно просто довести операцию до конца.
Если все сегменты ответили негативно на запрос о чтении информации,
то он будет перенаправлен к контроллеру кэш-памяти более низкого уровня и т. д. вплоть до контроллера оперативной памяти. Если же запрос был на запись, то контроллеру предстоит задача выбора сегмента, куда будет осуще-
ствлена операция. Для этого он анализирует строки-кандидаты, а если точ-
нее, то их биты состояния и прочие вспомогательные, после чего принимает решение согласно одному из популярных алгоритмов (мы их рассматривали в разделе, посвященному страничному управлению памятью):
● LRU (Least Recently Used, т. е. «наименее новый из запрашиваемых») –
запись идет в строку, находящаяся в которой информация запрашивалась в
последний раз наиболее давно;
● LRR (Least Recently Replaced, т. е. «наименее новый из записанных»),
также известный как FIFO (First In, First Out, т. е. «первым пришел, первым ушел») – вытесняется строка, находящаяся в которой информация характери-
зуется наиболее старой записью;
● LFU (Least Frequently Used, т. е. «наименее часто запрашиваемый») –
для записи выбирается строка, находящаяся в которой информация запраши-
валась |
наименее |
часто; |
● Random – запись идет в произвольно выбираемую строку. |
|
212

Как можно предположить, более сложные по сравнению с Random алго-
ритмы являются более эффективными, но используют более сложную об-
служивающую логику. LFU предполагает, что каждая строка кэш-памяти снабжена соответствующим счетчиком, обновляемым при каждом удачном запросе. LRU и LRR используют вместо него счетчик времени в той или иной форме, причем LRU требует его обновления при каждом удачном запросе. Random не предполагает каких-либо строчных счетчиков и вполне может быть основан на одном генераторе случайных чисел или чем-то подобном.
13.4. Размер строки, тега и индекса
Как уже рассматривалось выше, любая кэш-память подразделяется на так называемые строки (lines) (рис. 85). Было бы крайне нерационально наде-
лять каждый байт в кэш-памяти адресным полем, указывающим на его ме-
стонахождение в оперативной памяти, потому что это привело бы к очень тяжелым последствиям с точки зрения производственных затрат.
Рис. 85. Иллюстрация разделе-
ния кэш-памяти на строки
Структура записи в кэш
Типичная структура записи в кэше:
213

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ин- |
|
|
|
|
|
|
|
|
|
|
Блок данных |
|
|
|
смещение |
|
|
|
бит актуальности |
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
ег |
декс |
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Блок данных (кэш-линия) содержит непосредственную копию данных из основной памяти. Адрес памяти разделяется (от старших битов к младшим)
на тег, индекс и смещение. Бит актуальности означает, что данная запись со-
держит актуальную (самую свежую) копию. Длина поля индекса равна log2(cache rows) бит и соответствует ряду (строке) кэша, используемой для
записи. Длина смещения равна log2(data blocks).
Если рассмотреть 32-битное линейное физическое адресное пространст-
во, позволяющее непосредственно поддерживать до 4 Гб оперативной памя-
ти, каждый байт в кэш-памяти должен обслуживаться четырьмя адресными байтами! Кроме того, такая кэш-память была бы очень плоха с точки зрения производительности. Поэтому куда удобнее адресовать некоторые группы из соседствующих байтов, которые и будут формировать строки кэш-
памяти. На практике широко используются строки по 32 или 64 байт, хотя их размер может достигать даже 1 024 байт. Естественно, размер строки дол-
жен быть эквивалентен двойке в некоторой целой положительной степени.
Однако даже если требование по размеру выполнено, не каждая группа из соседствующих байтов может быть кэширована по причине дополнительного ограничения, известного как адресное выравнивание (address alignment). Дру-
гими словами, группа соседствующих байтов может быть помещена в строку кэш-памяти тогда и только тогда, когда ее начальный адрес выровнен по гра-
нице, равной размеру строки. Например, 32-байтная строка может быть за-
полнена информацией из оперативной памяти, находящейся по шестнадцате-
ричным (десятичным) адресам 00-1F (00-31), 20-3F (32-63), 40-5F (64-95) и т.
д.
214
Кроме иных преимуществ, это простое правило позволяет сократить число адресных битов в расчете на одну строку. Если точнее, то на 5 в выше-
приведенном примере, т. е. log2(32) = 5.
Наконец, строка кэш-памяти может быть либо полностью заполненной действительной информацией, либо полностью пустой, что равносильно быть заполненной недействительной информацией. Промежуточные вариан-
ты не поддерживаются. Из этого правила есть одно исключение: если у двух строк кэш-памяти имеется одно общее адресное поле, тогда их можно рас-
сматривать как подстроки одной строки, которые могут функционировать относительно независимо одна от другой.
Каждое адресное поле состоит из двух основных частей: динамическая
(tag), которая содержит старшие биты адреса: может быть изменена в про-
цессе работы и статическая (index), которая содержит младшие биты адре-
са: значение зафиксировано. (Важно помнить, что это никак не связано с ди-
намическими и статическими ячейками памяти). Для объяснения их функ-
ционального назначения необходимо ввести понятие логической сегмента-
ции оперативной памяти, а значит ввести некоторые допущения.
Допустим, что:
имеется некоторое физическое пространство оперативной па-
мяти, состоящее из M сегментов памяти одинакового размера, каждый из которых равен по размеру сегменту кэш-памяти.
Каждый сегмент памяти состоит из N строк одинакового раз-
мера, каждая из которых равна по размеру строке кэш-памяти.
Таким образом, чтобы получить адрес какой-либо строки па-
мяти, необходимо сначала определить номер ее сегмента памяти, затем номер данной строки в этом сегменте и объединить оба номера.
Для полноты картины осталось лишь подставить тег вместо номера сегмента и индекс вместо номера строки.
215

Размер тега строки кэш-памяти зависит от трех основных факторов: 1)
размера кэш-памяти; 2) ассоциативности кэш-памяти; 3) кэшируемого разме-
ра оперативной памяти. Этот размер рассчитывается по следующей формуле:
, |
|
где Stag – размер одного тега кэш-памяти, в битах; |
Smemory – максимальный |
кэшируемый размер оперативной памяти, в байтах; |
Scache – размер кэш- |
памяти, в байтах; A – ассоциативность кэш-памяти, в каналах.
Таким образом, для абстрактной системы с максимальным кэшируемым объемом оперативной памяти в 1 Гб и кэш-памятью (неважно какого уровня)
размером в 1 Мб с 2-канальной ассоциативностью потребуется ровно 11 бит для каждого тега. Другими словами, для адресации любым отдельным тегом
1 Гб / 512 Кб = 2048 сегментов памяти потребуется log2(2048) = 11 бит.
Следует уточнить, что ровно столько битов на тег необходимо для кэ-
ширования именно 1 Гб оперативной памяти при данной организации кэш-
памяти. Если сократить количество бит, то такой кэш останется работоспо-
собным, однако кэшируемый размер оперативной памяти уменьшится. На-
пример, 8 бит на тег позволят адресовать уже только 28 = 256 сегментов па-
мяти по 512 Кб, что позволит кэшировать лишь 128 Мб оперативной памяти.
Информация, находящаяся выше этой границы, кэшироваться не будет. Ас-
социативность кэш-памяти является непосредственным показателем ее логи-
ческой сегментации: сколько каналов, столько и сегментов.
Другими словами, кэш-память с N-канальной ассоциативностью (N-way set associative) предполагает, что информация, размещенная по некоторому адресу в оперативной памяти, может находиться (кэшироваться) в N местах
(строках) этой кэш-памяти.
216

Размер индекса зависит от размеров сегмента кэш-памяти и строки.
Фактически его должно быть достаточно для нумерации всех строк в преде-
лах отдельно взятого сегмента. Например, если имеется сегмент кэш-памяти в 512 Кб с 32-байтными строками, то размер индекса составит log2(512 Кб /
32б) = 14 бит.
Каждая строка в каком-либо сегменте имеет свой постоянный номер, ко-
торый не подлежит изменению, да и какой-либо необходимости в этом нет.
Если имеется N сегментов кэш-памяти, тогда всегда должно быть N
строк кэш-памяти с одинаковым индексом.
Увеличение размера строки при неизменном размере сегмента приведет к уменьшению размера индекса, а также и к уменьшению их количества вследствие уменьшения числа строк. В то же время увеличение размера строки приводит к увеличению задержек при загрузке строк из других уров-
ней кэш-памяти или оперативной памяти, равно как и при выгрузке, посколь-
ку возможности шинных интерфейсов небезграничны. К тому же больший размер строки ухудшает эффективность кэш-памяти вследствие большей степени ее засорения ненужной информацией.
Ко всему прочему каждая строка кэш-памяти обычно обладает некото-
рой избыточной информацией для надлежащего контроля за ошибками. Как правило, поля данных защищаются либо проверкой четности (parity checking)
на уровне отдельных байтов, либо одним из протоколов проверки и коррек-
ции ошибок (ECC – Error Checking and Correcting) на уровне целого поля,
большинство из которых основывается на алгоритме Хэмминга (the Hamming algorithm). Теги могут защищаться однобитовой проверкой четности, хотя эта практика распространена в значительно меньшей степени, чем защита полей данных. Тем не менее, какой бы из алгоритмов защиты информации ни был выбран, его обслуживающая логика привнесет сложности в существующую разработку и неминуемо отразится на задержках при работе. Если точнее, то
217
при каждой операции чтения контрольная сумма поля данных должна быть сосчитана и сверена с сохраненной. Наиболее тяжелым является случай час-
тичной записи в действительную строку, так как контрольная сумма должна быть сосчитана дважды: до и после изменения строки.
Ассоциативность является компромиссом. Проверка большего числа за-
писей требует больше энергии, площади чипа, и, потенциально, времени. Ес-
ли бы существовало 10 мест, в которые алгоритм вытеснения мог бы отобра-
зить место в памяти, тогда проверка наличия этого места в кэше потребовала бы просмотра 10 записей в кэше. С другой стороны, кэши с высокой ассоциа-
тивностью подвержены меньшему количеству промахов (см. ниже конфлик-
тующие промахи), и процессор тратит меньше времени на чтение из медлен-
ной основной памяти. Существует эмпирическое наблюдение, что удвоение ассоциативности (от прямого отображения к 2-канальной, или от 2-х к 4-
канальной) имеет примерно такое же влияние на интенсивность попаданий
(hit rate), что и удвоение размера кэша. Увеличение ассоциативности свыше 4
каналов приносит меньший эффект для уменьшения количества промахов
(miss rate), и, обычно, производится по другим причинам, например из-за пе-
ресечения виртуальных адресов.
13.5. Уровни кэша
Кэш центрального процессора разделен на несколько уровней. В уни-
версальном процессоре в настоящее время число уровней может достигать 3
(рис. 86). Кэш-память уровня N + 1, как правило, больше по размеру и мед-
леннее по скорости доступа и передаче данных, чем кэш-память уровня N.
218

Рис. 86. Примерная структура уровней кэша
Самой быстрой памятью является кэш первого уровня – L1-cache (рис.
87). По сути, она является неотъемлемой частью процессора, поскольку рас-
положена на одном с ним кристалле и входит в состав функциональных бло-
ков.
Рис. 87. Иерархия памяти
.
Важным уточнением рис. 87 является то, что чем выше уровень кэша,
тем он более емкий, но менее быстрый по сравнению с предыдущим. В со-
временных процессорах обычно кэш L1 разделен на 2 кэша: кэш команд (ин-
струкций) и кэш данных (в соответствии с гарвардской архитектурой).
Большинство процессоров без L1-кэша не могут функционировать. L1-
кэш работает на частоте процессора, и, в общем случае, обращение к нему может производиться каждый такт.
Зачастую является возможным выполнять несколько операций чте-
ния/записи одновременно. Латентность доступа обычно равна 2−4 тактам ядра. Объем обычно невелик – не более 128 Кбайт.
219
Вторым по быстродействию является L2-cache – кэш второго уровня,
обычно он расположен на кристалле, как и L1. В старых процессорах – набор микросхем на системной плате. Объем L2-кэша – от 128 Кбайт до 1−12
Мбайт.
В современных многоядерных процессорах кэш второго уровня, нахо-
дясь на том же кристалле, является памятью раздельного пользования – при общем объеме кэша в nM Мбайт на каждое ядро приходится по nM/nC Мбай-
та, где nC – количество ядер процессора. Обычно латентность L2-кэша, рас-
положенного на кристалле ядра, составляет от 8 до 20 тактов ядра.
Кэш третьего уровня наименее быстродействующий, но он может быть очень внушительного размера – более 24 Мбайт. L3-кэш медленнее преды-
дущих кэшей, но все равно значительно быстрее, чем оперативная память. В
многопроцессорных системах он находится в общем пользовании и предна-
значен для синхронизации данных различных L2.
Иногда существует и четвертый уровень кэша, обыкновенно он распо-
ложен в отдельной микросхеме. Применение кэша этого уровня оправдано только для высоко производительных серверов и мейнфреймов.
Для многоуровневых кэшей требуется делать новые архитектурные ре-
шения. Например, в некотором процессоре могут потребовать, чтобы все данные, хранящиеся в кэше L1, хранились также и в кэше L2. Такие пары кэшей называют строго инклюзивными (англ. inclusive). Другие процессоры
(например, AMD Athlon) могут не иметь подобного требования, тогда кэши называются эксклюзивными (исключительными) – данные могут быть либо в L1-, либо в L2-кэше, но никогда не могут быть одновременно в обоих. До сих пор другим процессорам (таким как Pentium II, Pentium III и Pentium 4) не требуется, чтобы данные в кэше первого уровня также размещались в кэше второго уровня, тем не менее, они продолжают так делать. Нет никакого уни-
220