Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Аппаратное обеспечение

Что каждый программист должен знать о памяти.

Часть 2: Кэш-память процессора

Оригинал: "Memory part 2: CPU caches"
Автор: Ulrich Drepper
Дата публикации: October 1, 2007
Перевод: Н.Ромоданов
Дата перевода: апрель 2012 г.
Назад Оглавление Вперед

3.3.5. Другие детали

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

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

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

Разработчики процессоров используют в настоящее время теги виртуальных адресов для кэш-памяти первого уровня. Эта кэш-памяти достаточно мала и ее можно очистить без особых проблем. Частичное освобождение кэш-памяти необходимо, по крайней мере, в случае, если изменяется дерево таблицы страниц процесса. Можно избежать полного сброса содержимого кэш-памяти в память в случае, если процессор имеет инструкции, в которых задан диапазон изменившихся виртуальных адресов. Если учесть низкую латентность кэш-памяти L1i и L1d (~ 3 циклов), то использование виртуальных адресов является почти обязательным.

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

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

Еще одной деталью кэш-памяти, которой программисты интересуются сравнительно мало, это стратегия замены кэш-памяти. В большинстве вариантов кэш-памяти в первую очередь удаляются те элементы, обращение к которым не было дольше всего (Least Recently Used - LRU). Это, по умолчанию, всегда хорошая стратегия. При наличии большей ассоциативности (и ассоциативность, действительно, в связи с добавлением большего количества ядер может в ближайшие годы расти и дальше) ведение списка элементов LRU становится все более и более дорогим, и нам следовало бы рассматривать другие подходящие стратегии.

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

С появлением виртуализации все становится еще сложнее. Теперь распределение физической памяти контролируется даже не операционной системой. За физическое назначение памяти ответственность несет монитор виртуальных машин (VMM, иначе гипервизор).

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


Назад Оглавление Вперед