Оценивая быстродействие кэш-памяти третьего уровня, реализованной на кристалле процессора AMD EPYC 7452, мы столкнулись с ситуацией, требующей детального рассмотрения. Прежде чем, заняться ее анализом, изучим особенности организации L3-кэш у семейства процессоров EPYC Rome, разработанных с использованием архитектуры Zen 2.
Собственно, L3 не является составной частью архитектуры процессорного ядра Zen 2. Классический подход к разработке современных процессоров общего назначения ограничивает возможности ядра кэш-памятью первого и второго уровней. Но Zen 2 на третьем уровне для кэширования инструкций и данных формует сущность CCX (Compute Complex), в которую может быть погружено 4 процессорных ядра. Они совместно используют блок кэш-памяти L3 объемом 16 МБ. Пара таких комплексов составляет чиплет CCD — замечательное изобретение AMD. Всего может быть до 8 таких чиплетов, что дает основание говорить о наличии максимум 256 МБ кэш-памяти L3.
В случае 32-ядерного EPYC 7452, в основе которого лежат 4 чиплета CCD, кэш-память третьего уровня ограничена 128 мегабайтами.

Топологическая иерархия AMD Rome
Анализируем CPUID
Исходя из сказанного, чисто теоретически, в распоряжении одного ядра может находиться не более 16 МБ L3, а в условиях реальной эксплуатации — и того меньше. Проверим вышесказанное, с помощью утилиты Java CPUID.

Параметры комплекса CCX согласно результатам выполнения инструкции CPUID, функция 8000001Dh
CPUID функция 8000001Dh позволяет получить информацию о кэш-памяти одного комплекса CCX. Каждое его ядро оснащено L1-кэшем для инструкций и данных объемом по 32 килобайта каждый; объем кэш-памяти L2 составляет 512 килобайт. При этом L1 и L2 являются ресурсами приватными для каждого из ядер. Заметим, что места в L1-кэш для инструкций в процессорах второго поколения AMD EPYC выделено в два раза меньше, чем было в первом поколении этих серверных чипов.
Параметр Max. logical CPUs sharing this cache для L1 и L2 равен двум — это количество логических процессоров, совместно использующих L1 и L2, что с учетом технологии SMT означает: два логических CPU соответствуют одному ядру. Для L3-кэш этот параметр равен 8 — количество ядер, совместно использующих блок L3, равно 4.

Суммарный объем кэш-памяти L3 на одно процессорное гнездо (согласно CPUID функции 80000006h)
Чтобы определить полный объем L3 для процессора, воспользуемся CPUID функцией 80000006h. Эта величина составляет 128 MB — топология L3 представлена восемью кластерами по 16 MB. Данные CPUID функции 8000001Dh говорят о том, что ассоциативность L3 (Ways of associativity) равна 16. На скриншоте функции 80000006h значение L3 Unified Cache Associativity находится в состоянии Reserved, что следует из официальной документации.
Обратим также внимание на параметр L2 data TLB for 4KB pages number of entries, который равен 800h, что в десятичном представлении дает 2048; он нам понадобится позже.

До сих пор считалось, что 16-вариантной ассоциативности соответствует значение битового поля EDX.[15-12], равное 8. В нашем случае CPUID возвращает 9, что может означать или запаздывание в документации, или особое архитектурное решение.
Из маркетинговых материалов AMD следует, что латентность L3 в процессорах семейства EPYC 7002 обусловлена временем, соответствующим 40 процессорным тактам (для предыдущего семейства Naples это значение было несколько ниже — латентность L3-кэш составляла 35 тактов), что хорошо согласуется с данными, полученными в ходе эксперимента.
Измерение латентности в этом эксперименте основано на идее использования прочитанных данных в качестве адреса для следующего чтения. При этом подавляются спекулятивные способности CPU, поскольку невозможно опережающее выполнение следующего чтения, искажающее результат. Процесс связан с доступом к фрагментированным данным с рандомизацией адресов, поэтому каждая следующая операция с высокой вероятностью будет оперировать с новой страницей и потребует загрузки нового дескриптора в TLB. Метрики мы будем получать с помощью своего программного продукта, предназначенного для измерения производительности кэш и оперативной памяти — утилиты NUMA CPU and RAM Benchmark (сокращенно NCRB).
Про страницы, TLB и латентность L3-кэш
Как известно, механизм трансляции страниц (или paging) отображает виртуальное адресное пространство приложения на физическую память платформы. Каждая страница описывается дескриптором Page Table Entry (PTE). За кэширование таких дескрипторов отвечает блок Translation Lookaside Buffer (TLB).
Классическая схема, принятая еще во времена i386, гранулирует оперативную память четырех килобайтными страницами, что хотя и экономно, но связано с серьезными накладными расходами в современных условиях. Сегодня доступен и один из продвинутых способов — гранулярность «большими страницами», размером в 2 МБ. Выгоды от его использования очевидны: в большинстве приложений растет эффективность операций с ОЗУ.
Терминологическое уточнение
В нашем эксперименте ОС предоставляет, а бенчмарк NCRB использует большие страницы, формируемые путем пропуска одного подкаталога страниц (PTE), действующего на последней стадии трансляции линейного адреса в физический. Высвобождаемые при этом адресные биты становятся частью адреса байта внутри страницы. В процессорной архитектуре x64 (а также в IA32 + PAE) это увеличивает размер страницы до 2 MB, в IA32 это увеличивает размер страницы до 4 MB. Как сказано выше, стандартные страницы со времен процессора i386, всегда имеют размер 4 KB.
Буфер ассоциативной трансляции
И хотя польза от «больших страниц» иногда сомнительна, с переходом в режим Large Pages размер адресуемой области увеличивается с 4 KB (Normal Pages) до 2 MB (Large Pages), а количество выделенных для этого дескрипторов пропорционально уменьшается. В результате снижается нагрузка на TLB — один из важнейших уровней кэш-памяти, который смело можно назвать «серым кардиналом» производительности. Рассмотрим влияние буфера ассоциативной трансляции на латентность кэш-памяти L3-уровня в процессоре EPYC 7452.
TLB и латентность L3-кэш
Вернувшись к иллюстрации результатов функции CPUID 80000006h, приведенной в начале статьи, обратим внимание на L2 data TLB for 4KB pages number of entries. Согласно CPUID, объем буфера ассоциативной трансляции, кэширующего дескрипторы страниц, составляет 800h = 2048 элементов. Они позволяют адресовать «нормальными» 4 KB страницами диапазон памяти в 2048 * 4KB = 8192K = 8MB.
Размер кластера L3-кэша, обслуживающего 4 процессорных ядра CCX, вдвое превышает эту границу. Выполним однопоточное тестирование латентности L3, чтобы оценить зависимость этого параметра от способа трансляции страниц оперативной памяти.
На графиках латентности меньшие значения соответствуют бо́льшей производительности

Зависимость латентности однопоточного доступа от объема обрабатываемого блока в окрестности общего пространства L3 = 16MB одного кластера CCX в режиме Normal Pages
Логично предположить, что на графике латентности L3 в режиме 4KB страниц, точка перегиба при X = 8 MB вызвана исчерпанием L2 Data TLB, это приводит к TLB-промахам и необходимости читать дескрипторы из ОЗУ, что, очевидно, займет значительно больше тактов, чем получение их из TLB. Далее, в окрестности X = 16 MB происходит исчерпание объема кластера L3, что также сопровождается точкой перегиба.

Зависимость латентности однопоточного доступа от объема обрабатываемого блока в окрестности общего пространства L3 = 16MB одного кластера CCX в режиме Large Pages
В данном примере использование Large Pages почти нивелирует влияние фактора TLB на результат теста. Что и понятно: «большие страницы» позволяют адресовать диапазон памяти в 2048 * 2MB = 4096MB = 4GB, хотя при этом в исследуемом процессоре количество элементов L2 TLB для обычных и больших страниц совпадает.
В силу особенностей страничной трансляции, при расчетах объемов данных, вызывающих переполнение TLB, ключевое значение имеет не размер собственно дескриптора страницы, а размер диапазона памяти, доступ к которому обеспечивает один дескриптор.
Пропускная способность L3-кэш
В отличие от латентности пропускная способность измеряется на операциях с достаточно большими и непрерывными блокам данных. Здесь, один раз попав на страницу, бенчмарк гарантированно прочитает или запишет (в зависимости от типа теста) весь объем страницы, прежде чем перейти к следующей.
Сказанное означает, что частота промахов TLB в тестах пропускной способности должна быть ниже, чем в тестах латентности, значит, к фактору Large Pages измерения латентности должны быть более чувствительны, чем измерения пропускной способности.
На графиках пропускной способности бо́льшие значения соответствуют бо́льшей производительности

Зависимость однопоточной скорости чтения от объема обрабатываемого блока в окрестности общего пространства L3 = 16MB одного кластера CCX в режиме Normal Pages

Зависимость однопоточной скорости чтения от объема обрабатываемого блока в окрестности общего пространства L3 = 16MB одного кластера CCX в режиме Large Pages
Вместе с тем, опыт продемонстрировал, что оба показателя (латентность и пропускная способность) не лишены влияния фактора TLB. Заметим, что в силу специфики нашего примера читаемый блок помещается в кэш-память исследуемого уровня (объемом 16MB), а картирующий контекст, необходимый для обслуживания операции чтения в режиме 4KB страниц не помещается в TLB (объем которого позволяет адресовать диапазон размером 8MB).
Подводя итоги
В ситуации, когда процессорные ядра достигли частотного порога насыщения, а их количество напрямую не может определять производительность всего вычислительного комплекса, решающее значение имеет оснащение CPU умными алгоритмами, где не последнее место отводится алгоритмам кэширования. В процессорах семейства AMD Rome кроме приватных кэш-ресурсов L1 и L2 на первых ролях агрегирований L3-кэш. Его задача — обеспечить производительность CCX-кластера в частности и всего процессора в целом, а также снизить нагрузку на подсистему DRAM, обслуживаемую отдельным кристаллом I/O Hub.
Проведенный эксперимент продемонстрировал зависимость даже в однопоточном режиме пропускной способности и латентности L3 от механизма трансляции линейного адреса в физический. Стоит предполагать, что при мультипоточном использовании L3 задержки при доступе к этому разделяемому ресурсу быстродействующей памяти будут нарастать.
В основе обнаруженного феномена — зависимость от объема и организации буфера ассоциативной трансляции. Нетрудно заметить, что ситуация, при которой данные обрабатываемого блока помещаются в кэш-памяти, а картирующий контекст, необходимый для трансляции его страниц не помещается в TLB (в режиме 4K страниц), характерна для блоков, объем которых сравним с объемом L3. В этой ситуации роль TLB становится критически важной. Протестированный процессор AMD EPYC 7452 32-Core доказал это.
Как следует из графиков латентности, в режиме Large Pages имеет место полуторакратное снижение величины задержки при доступе к L3 при объеме блока X=16MB. Этот факт заслуживает внимания разработчиков коммерческого программного обеспечения, ответственно относящихся к оптимизации кода — сценарий нашего синтетического теста моделирует доступ к фрагментированным данным. Несмотря на все сложности внедрения «больших страниц», их использование в прикладных задачах (системы управления базами данных и т.п.) выглядит оправдано с точки зрения борьбы за каждую наносекунду процессорного времени.