Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
46
Добавлен:
20.03.2015
Размер:
1.37 Mб
Скачать

8.3.2. Алгоритмы замещения

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

Главная идея, которой следует руководствоваться, принимая такое решение, состоит в следующем: в памяти должны оставаться бло­ки, для которых вероятность того, что они понадобятся в ближайшем будущем, максимальна. Но как их определить? Здесь можно опереться на принцип локали­зации ссылок. Так как повторяющиеся команды, лежащие в пределах некоторой области, выполняются в течение определенного времени, существует большая ве­роятность того, что блоки, обращение к которым производилось недавно, очень скоро потребуются снова. Поэтому, когда требуется освободить место для нового блока, имеет смысл удалить из кэша тот блок, к которому дольше всего не было обращений. Алгоритм работы этого блока называется алгоритмом удаления наи­более давно использовавшихся элементов (Least Recently Used, LRU).

Для использования алгоритма LRU контроллер кэша должен отслеживать об­ращения ко всем блокам кэша. Предположим, что ему нужно следить за обраще­ниями к блоку LRU из четырехблочного множества множественно-ассоциатив­ного кэша. Для каждого блока может использоваться 2-разрядный счетчик. При попадании в кэш счетчик соответствующего блока устанавливается в 0. Счетчи­ки, значения которых были больше значения данного счетчика, увеличиваются на 1. Когда в кэше не оказывается нужного блока, а в множестве еще есть место, счетчик нового блока устанавливается в 0, а значения других счетчиков увеличи­ваются на 1. Если же множество заполнено, блок, счетчик которого равен 3, уда­ляется, а на его место помещается новый блок. Значения остальных трех счетчи­ков увеличиваются на 1. Нетрудно убедиться, что при использовании такого ал­горитма значения счетчиков четырех блоков всегда будут разными.

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

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

8.3.3. Примеры технологий отображения

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

Давайте проанализируем изменения в кэше данных, вызванные выполнени­ем следующей задачи. Массив чисел А размером 4 х 10, в котором каждое число занимает одно слово, хранится в основной памяти по шестнадцатеричным адре­сам от 7А00 до 7А27. Элементы этого массива хранятся в порядке следования столбцов. На рис. 8.7 показано, как выделяются теги из адресов памяти при раз­ных технологиях отображения. Обратите внимание, что в нашем примере нет спе­циальных битов, используемых для идентификации слова внутри блока, как на рис. 8.4, 8.5, 8.6, поскольку мы предполагаем, что каждый блок содержит только одно слово. Приложение нормализует значения элементов первой строки масси­ва А относительно среднего значения элементов этой строки. Таким образом, нам нужно вычислить среднее значение элементов строки и разделить на него значе­ние каждого из элементов. Эту задачу можно выразить так:

Код, выполняющий указанную задачу, приведен на рис. 8.8. В программе на машинном языке для ссылки на элементы массива будут использоваться адреса памяти. Для хранения суммы и среднего значения предназначены переменные SUM и AVE. Эти переменные, равно как и индексные переменные i и j, при вы­числениях хранятся в регистрах процессора.

Рис. 8.7. Массив, хранящийся в основной памяти

Рис. 8.8. Код для примера

Кэш с прямым отображением

На рис. 8.9 показано, как изменяется содержимое кэша с прямым отображением. В столбцах таблицы приведено содержимое кэша после проходов по двум циклам программы, представленной на рис. 8.8. Например, после второго прохода по первому циклу (j = 1) в кэше содержатся элементы А(0,0) и А(0,1). Они хранятся в блоках 0 и 4 с учетом значений трех младших разрядов их адресов. На следую­щем проходе элемент А(0,0) заменяется элементом А(0,2), имеющим тот же адрес блока. Обратите внимание, что элементы массива соответствуют только двум блокам кэша, а остальные блоки остаются неизменными — в конце процесса нор­мализации они содержат те же данные, что до его начала.

Позиция блока

0

1

2

3

4

5

6

7

Содержимое кэша данных после прохода по циклу:

j=1

j=3

j=5

j=7

j=9

i=6

i=4

i=2

i=0

А(0,0)

А(0,2)

А(0,4)

А(0,б)

А(0,8)

А(0,6)

А(0,4)

А(0,2)

А(0,0)

А(0,1)

А(0,3)

А(0,5)

А(0,7)

А(0,9)

А(0,7)

А(0,5)

А(0,3)

А(0,1)

Рис. 8.9. Содержимое кэша данных с прямым отображением

После десяти проходов по первому циклу (j = 9) в кэше хранятся элементы А(0,8) и А(0,9). Поскольку при выполнении второго цикла элементы обрабатыва­ются в обратном порядке, то элементы, необходимые на первых двух проходах этого цикла, будут находиться в кэше. На третьем проходе (i = 7) элемент А(0,8) будет заменен элементом А(0,7), затем элементом А(0,6) и т. д. Таким образом, во время выполнения второго цикла в кэше будет заменено восемь элементов.

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

Ассоциативный кэш

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

Позиция блока

0

1

2

3

4

5

6

7

Содержимое кэша данных после выполнения цикла:

j = 7

j = 8

j = 9

i = 1

i = 0

А(0,0)

А(0,8)

А(0,8)

А(0,8)

А(0,0)

А(0,1)

А(0,1)

А(0,9)

А(0,1)

А(0,1)

А(0,2)

А(0,2)

А(0,2)

А(0,2)

А(0,2)

А(0,3)

А(0,3)

А(0,3)

А(0,3)

А(0,3)

А(0,4)

А(0,4)

А(0,4)

А(0,4)

А(0,4)

А(0,5)

А(0,5)

А(0,5)

А(0,5)

А(0,5)

А(0,6)

А(0,6)

А(0,6)

А(0,6)

А(0,6)

А(0,7)

А(0,7)

А(0,7)

А(0,7)

А(0,7)

Рис. 8.10. Содержимое ассоциативного кэша данных

Множественно-ассоциативный кэш

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

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

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

Множество 1

Множество 2

Содержимое кэша данных после выполнения цикла:

j = 3

j = 7

j = 9

i = 4

i = 2

i = 0

А(0,0)

А(0,4)

А(0,8)

А(0,4)

А(0,4)

А(0,0)

А(0,1)

А(0,5)

А(0,9)

А(0,5)

•А(0,5)

А(0,1)

А(0,2)

А(0,6)

А(0,6)

А(0,6)

А(0,2)

А(0,2)

А(0,3)

А(0,7)

А(0,7)

А(0,7)

А(0,3)

А(0,3)

Рис. 8.11. Содержимое множественно-ассоциативного кэша данных