|
Иерархическая модель
В любой отдельно взятой компьютерной системе кэш-память логически и
физически подразделяется на так называемые уровни. Например, в абстрактной
машине с 32Кб внутренней (в ядре процессора) и 1Мб внешней (на процессорном
модуле или на материнской плате) кэш-памяти первая будет считаться кэш-памятью
1-го уровня, а вторая — кэш-памятью 2-го уровня. В современных
компьютерных системах количество уровней кэш-памяти может доходить до четырёх,
хотя наиболее часто используется двухуровневая модель. Кэш-память 1-го уровня
обычно подразделяют на кэш команд (instruction cache, I-cache) и кэш данных
(data cache, D-cache) — так называемая гарвардская архитектура (Harvard
architecture). Хотя I-cache и D-cache обычно имеют одинаковый размер, это
необязательное условие. В то же время их почти всегда встраивают в процессорные
ядра с целью достижения максимальной производительности. История знает не так
много примеров противного, да и многие из них приходятся на представителей
архитектуры PA-RISC. Hewlett-Packard PA-7000 располагали I-cache и D-cache в
256Кб каждый, PA-7100 и PA-7150 — в 1Мб и 2Мб соответственно, PA-8000
— в 1Мб каждый, PA-8200 — в 2Мб каждый. Однако, все эти процессоры
не отличались высокими тактовыми частотами, поэтому организация работы их
I-cache и D-cache на полной частоте ядер с допустимыми задержками на доступ не
составила проблемы. Тем не менее, эти процессоры в прошлом характеризовались
очень хорошей производительностью. Если взять для оценки быстродействия
показатели набора тестовых программ SPEC95, то рабочую станцию HP Visualize C200
на основе 200МГц PA-8000 можно считать эквивалентной DEC Personal WorkStation
600au с 600МГц Alpha 21164A с точки зрения производительности на вещественных
задачах (21,4 против 21,3), хотя на целочисленных она была медленнее последней
приблизительно на 20% (14,3 против 18,4). Это совершенно не означает, что та или
иная архитектура хуже или лучше, но должно приводить к выводу, что тактовая
частота ядра и организация кэш-памяти являются лишь двумя факторами из многих,
определяющих быстродействие некоторой аппаратной реализации.
Существует несколько причин, согласно которым разделённые кэши более
предпочтительны на 1-м уровне, чем унифицированные (U-cache). Выборку из I-cache
и D-cache обычно осуществляют разные функциональные устройства: декодер и
планировщик команд (I-box) из I-cache, a блоки целочисленных (E-box) и
вещественных (F-box) вычислений — из D-cache; E-box ещё часто называют
арифметико-логическим устройством. В операциях с кэшами также непосредственно
принимают участие блок загрузки/сохранения (A-box) с контроллером кэш-памяти и
системной шины (C-box). Кстати, каждое функциональное устройство обычно состоит
из одного или нескольких исполнительных конвейеров (execution pipelines).
I-cache и D-cache работают с очень низкими задержками при доступе, так как их
увеличение приводит к ощутимому падению производительности на большинстве задач.
Поэтому приходится жертвовать размерами кэшей, обычно составляющими от 8Кб до
64Кб — большой кэш сложнее разместить на кремниевой подложке и обеспечить
его синхронизацию. Другими словами, если некоторую кэш-память увеличить в
размере при сохранении её внутренней организации, то на поиск некоторой нужной
информации потребуется неизбежно больше времени, равно как и на её перемещение к
выходу. К тому же, увеличение числа конвейеров функциональных устройств, активно
использующих некоторую кэш-память, требует увеличения количества портов доступа
(о которых речь пойдёт позже), что само по себе является нелёгкой задачей. Кроме
того, U-cache подвержен и другим недостаткам, например, сбросу данных при сбросе
команд, который обычно проводится при обработке системных исключительных
ситуаций, имеющих целью очистку процессорных конвейеров и перезапуск их по
новому адресу. В то же время сброс I-cache с виртуальным тэгированием при
плановом переключении задач также является вполне обычным делом. С другой
стороны, U-cache позволяет более эффективно заполнять себя информацией, то есть
может изменять соотношение количества содержащихся команд и данных в зависимости
от специфики выполняемой задачи.
Кэш-память 2-го уровня почти всегда является унифицированной, хотя из этого
правила есть несколько известных исключений. Например, HARP-1 (Hitachi Advanced
RISC Processor) архитектуры PA-RISC 1.1 располагал 8Кб I-cache и 16Кб D-cache,
которые поддерживались внешними кэшами команд и данных в размере по 512Кб
каждый. Далее, дизайн SPARC64 V от HAL Computer (не путать с одноимённым
процессором от Fujitsu, который и производился) предполагал наличие 32Кб I-cache
(расширенный при помощи trace cache на 1024 записи) и 8Кб D-cache, которые
дополнялись встроенными кэшами команд и данных в размере 256Кб и 512Кб
соответственно, а также внешней унифицированной кэш-памятью в размере до 64Мб.
Среди наиболее современных примеров выделяется Intel Itanium 2
(подразумевается модель под кодовым названием Montecito). Каждое из его двух
ядер было наделено собственными 16Кб I-cache и 16Кб D-cache, а также встроенными
кэшами команд и данных 2-го уровня в размере 1Мб и 256Кб соответственно, которые
дополнялись встроенной унифицированной кэш-памятью 3-го уровня в размере 12Мб.
Основной причиной популярности унифицированной кэш-памяти 2-го уровня является
тот факт, что вышестоящие I-cache и D-cache обычно удовлетворяют 80-90% всех
запросов, поэтому некоторое увеличение задержек на доступ и доставку информации
из этой кэш-памяти оправдывается более высокой эффективностью (hit rate),
следующей из увеличения её размера и количества каналов ассоциативности. Если
кэш-память 2-го уровня встраивается в ядро процессора, то её можно называть
S-cache (secondary cache, то есть второстепенной кэш-памятью). Если некоторый
процессор предусматривает наличие встроенной кэш-памяти 3-го уровня, то её удобно
именовать T-cache (ternary cache, то есть третьестепенная кэш-память). Иногда
может устанавливаться внешняя кэш-память, физически обычно состоящая из
стандартных дискретных микросхем статической памяти и называемая B-cache (back-up
cache, то есть резервная кэш-память). Как правило, B-cache является последним
уровнем в иерархии кэш-памяти. В отличие от встроенной кэш-памяти, он может
управляться как C-box процессора, так и системной логикой, или же ими обоими
сообща. В целом же, каждый низлежащий уровень кэш-памяти превышает в размере
предыдущий, но уступает ему в быстродействии.
Иерархия уровней кэш-памяти лучше всего прослеживается в работе процессора.
Если в момент выполнения некоторой команды данных для неё не окажется в
регистрах, то они будут затребованы из ближайшего уровня кэш-памяти, то есть из
D-cache. В случае их отсутствия запрос будет перенаправлен в следующий уровень
кэш-памяти и так далее. В худшем случае данные будут доставлены непосредственно
из оперативной памяти, хотя возможен и более плачевный исход, если подсистема
управления виртуальной памятью операционной системы успела вытеснить их в
swap-файл (или в swap-раздел, что по сути неважно), то есть на жёсткий диск.
Потери времени на доставку необходимого кванта данных размером в регистр из
оперативной памяти обычно составляют от десятков до сотен процессорных тактов, а
в случае подгрузки с жёсткого диска речь уже может идти о сотнях тысяч и
миллионах тактов.
|