Почему кэш-память L1 и L2 расходует пространство, сохраняя одни и те же данные?

Я не знаю, почему L1 Cache и L2 Cache сохраняют одни и те же данные.

Например, допустим, мы хотим получить доступ к памяти [x] в первый раз. Память [x] сначала отображается в кэш L2, затем тот же фрагмент данных отображается в кэш L1, откуда регистр ЦП может получать данные.

Но у нас есть дублированные данные, хранящиеся в кэш-памяти L1 и L2, не является ли это проблемой или, по крайней мере, тратой дискового пространства?

1 ответ

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

Не все кэши такие. Политика включения кэша для внешнего кэша может быть включающей, исключающей или не включающей / не исключающей.

NINE является "нормальным" случаем, не поддерживающим ни одного специального свойства, но L2 имеет тенденцию иметь копии большинства строк в L1 по причине, которую вы описали в вопросе. Если L2 менее ассоциативен, чем L1 ( как в Skylake-клиенте), и шаблон доступа создает много пропусков конфликтов в L2 (маловероятно), вы можете получить приличный объем данных, который есть только в L1. И, возможно, другими способами, например, с помощью аппаратной предварительной выборки или из-за вытеснения данных L2 из-за выборки кода, потому что реальные процессоры используют разделенные кэши L1i / L1d.


Чтобы внешние кэши были полезны, вам нужен какой-то способ ввода данных, чтобы вы могли получить удар L2 через некоторое время после того, как линия была удалена из меньшего L1. Наличие внутренних кэшей, таких как извлечение L1d через внешние кэши, дает вам это бесплатно и имеет некоторые преимущества. Вы можете поместить логику аппаратной предварительной выборки во внешний или средний уровень кэша, который не должен быть столь же высокопроизводительным, как L1. (Например, процессоры Intel имеют большую часть своей логики предварительной выборки в частном L2d для каждого ядра, но также и некоторую логику предварительной выборки в L1d).

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

С эксклюзивным L2, промах L1 / L2 может просто поменять линии между L1d и L2, если L1d нужно что-то выселить из этого набора.

Некоторые процессоры действительно используют L2, который не относится к L1d (например, AMD K10 / Barcelona). Оба этих кеша являются частными кешами на ядро, а не общими, так что это как простая ситуация L1 / L2 для одноядерного процессора, о которой вы говорите.


Все становится сложнее с многоядерными процессорами и общими кэшами!

Общий кэш L3 Барселоны также в основном исключает внутренние кэши, но не строго. Дэвид Кантер объясняет:

Во-первых, это в основном эксклюзив, но не совсем так. Когда строка отправляется из кэша L3 в кэш L1D, если строка кэша используется совместно или, вероятно, будет использоваться совместно, она останется в L3, что приведет к дублированию, которое никогда не произойдет в полностью исключительной иерархии. Выбранная строка кэша, вероятно, будет использоваться совместно, если она содержит код или если данные были ранее предоставлены (история совместного использования отслеживается). Во-вторых, политика выселения для L3 была изменена. В K8, когда строка кеша вводится из памяти, псевдо-наименьший недавно использованный алгоритм будет удалять самую старую строку в кеше. Тем не менее, в Барселоне L3, алгоритм замены был изменен, чтобы также учитывать совместное использование, и он предпочитает исключать неразделенные линии.

Преемником AMD K10 / Barcelona является бульдозер. https://www.realworldtech.com/bulldozer/3/ указывает, что разделяемый L3 бульдозера также является кэш-памятью жертвы и, следовательно, в основном исключает L2. Это, вероятно, как Барселона L3.

Но Bulldozer L1d - это небольшой сквозной кэш - память записи с еще меньшим (4 КБ) буфером для записи, поэтому он в основном включает L2. Пропускная запись L1d в Bulldozer обычно считается ошибкой в ​​мире проектирования ЦП, и Райзен вернулся к нормальному 32-килобайтному L1d с обратной записью, который Intel использовала все время (с отличными результатами). Пара слабых целочисленных ядер образует "кластер", который разделяет блок FPU/SIMD и разделяет большой L2, который "в основном включительно". (то есть, вероятно, стандартная NINE). Эта кластерная вещь является альтернативой бульдозеру SMT / Hyperthreading, которую AMD также выбрала для Ryzen в пользу обычного SMT с массивно широким ядром.

У Райзена также есть некоторая исключительность между кластерами ядра (CCX), но я не стал вдаваться в подробности.


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

Intel Nehalem и более поздние версии используют большой общий кэш L3, включающий теги. Для строк, которые модифицированы / исключены (MESI) в частном кэш-памяти L1d или L2 (NINE) для каждого ядра, теги L3 по-прежнему указывают, какие ядра (могут) иметь копию строки, поэтому запросы от одного ядра для эксклюзивного доступа к строка не должна передаваться всем ядрам, а только тем ядрам, которые все еще могут ее кэшировать. (то есть это Snoop-фильтр для когерентного трафика, который позволяет центральным процессорам масштабироваться до десятков ядер на чип, не затопляя друг друга запросами, даже если они даже не делят память).

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

С Skylake-X (Skylake-сервер / SKX / SKL-SP) Intel отказалась от этого и сделала L3 NINE и лишь немного больше, чем общий размер L2 на ядро. Но есть все еще фильтр snoop, у него просто нет данных. Я не знаю, что Intel планирует сделать для будущих (двухъядерных?)/ Четырехъядерных / шестигранных ноутбуков / настольных чипов (например, Cannonlake / Icelake). Это настолько мало, что их классическая кольцевая шина все равно будет великолепна, поэтому они могли бы продолжать делать это в мобильных / настольных частях и использовать только сетку в высокопроизводительных / серверных частях, как в Skylake.


На форуме Realworldtech обсуждаются вопросы "все включено" и "исключено" и "не включено":

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

Кроме того, L2 кэширует запросы на фильтрацию в L3, поэтому, когда его алгоритму LRU необходимо отбросить строку, тот, который он видел менее всего недавно, может легко быть тем, который постоянно остается горячим в L2 / L1 ядра. Но когда инклюзивный L3 решает отбросить строку, он должен выселить ее из всех внутренних кешей, у которых она тоже есть!

Дэвид Кантер ответил интересным списком преимуществ для инклюзивных внешних кэшей. Я думаю, что он сравнивает с эксклюзивными кешами, а не с NINE. Например, его утверждение о том, что совместное использование данных проще только в отношении к исключительным кешам, где, я думаю, он предполагает, что строго исключительная иерархия кеша может привести к выселению, когда несколько ядер хотят одну и ту же строку даже в режиме совместного использования / только для чтения.

Другие вопросы по тегам