Где задокументирован кэш памяти L1 процессоров Intel x86?
-
23-08-2019 - |
Вопрос
Я пытаюсь профилировать и оптимизировать алгоритмы, и я хотел бы понять специфическое влияние кэшей на различные процессоры.Для последних процессоров Intel x86 (напримерQ9300), очень трудно найти подробную информацию о структуре кэша.В частности, большинство веб-сайтов (включая Intel.com) что спецификации постпроцессора не содержат никаких ссылок на кэш L1.Это потому, что кэш L1 не существует или эта информация по какой-то причине считается неважной?Есть ли какие-либо статьи или обсуждения об устранении кэша L1?
[редактировать] После запуска различных тестов и диагностических программ (в основном тех, которые обсуждались в ответах ниже) я пришел к выводу, что мой Q9300, похоже, имеет кэш данных объемом 32 Кб L1.Я до сих пор не нашел четкого объяснения тому, почему эту информацию так трудно получить.Моя текущая рабочая теория заключается в том, что детали кэширования L1 теперь рассматриваются Intel как коммерческая тайна.
Решение
Найти спецификации в кешах Intel практически невозможно.Когда в прошлом году я проводил курс по кэшам, я попросил друзей из Intel (в группе компиляторов) и они не смог найти спецификации.
Но подождите!!! Джед, благослови его душа, говорит нам, что в системах Linux вы можете выжать много информации из ядра:
grep . /sys/devices/system/cpu/cpu0/cache/index*/*
Это даст вам ассоциативность, установленный размер и кучу другой информации (но не задержку).Например, я узнал, что, хотя AMD рекламирует свой 128-килобайтный кэш L1, на моей машине AMD есть разделенный кэш I и D по 64 КБ каждый.
Два предложения, которые сейчас в основном устарели благодаря Джеду:
AMD публикует гораздо больше информации о своих кэшах, так что вы можете, по крайней мере, получить некоторую информацию о современном кэше.Например, прошлогодние кэши AMD L1 выдавали два слова за цикл (пик).
Инструмент с открытым исходным кодом
valgrind
внутри него есть всевозможные модели кэша, и это бесценно для профилирования и понимания поведения кэша.Он поставляется с очень хорошим инструментом визуализацииkcachegrind
который является частью KDE SDK.
Например:в третьем квартале 2008 года AMD К8/К10 Процессоры используют 64-байтовые строки кэша, с разделением кэша L1I / L1D на 64 Кб каждая.L1D является двусторонним ассоциативным и эксклюзивным с L2, с задержкой в 3 цикла.Кэш L2 является 16-полосным ассоциативным, а задержка составляет около 12 циклов.
Процессоры семейства AMD Bulldozer используйте разделенный L1 с 4-полосным ассоциативным L1D размером 16 КБ на кластер (по 2 на ядро).
Процессоры Intel долгое время сохраняли L1 неизменным (от Pentium M до Хасвелл в Скайлейк и, предположительно, многие поколения после этого):Разделите 32 Кб на каждый I- и D-кэши, причем L1D будет 8-полосным ассоциативным.64 байта строк кэша, соответствующих размеру пакетной передачи DDR DRAM.Задержка загрузки-использования составляет ~ 4 цикла.
Также смотрите x86 отметьте wiki для ссылок на дополнительные данные о производительности и микроархитектуре.
Другие советы
Это Руководство Intel: Справочное руководство по оптимизации архитектур Intel® 64 и IA-32 содержит достойное обсуждение соображений, касающихся кэша.
Страница 46, Раздел 2.2.5.1 Справочное руководство по оптимизации архитектур Intel® 64 и IA-32
Даже MicroSlop осознает необходимость в дополнительных инструментах для мониторинга использования кэша и производительности, и имеет Функция GetLogicalProcessorInformation() пример (... прокладывая новые пути в создании смехотворно длинных имен функций в процессе) Я думаю, что я буду кодировать.
ОБНОВЛЕНИЕ I:Hazwell увеличивает производительность загрузки кэша в 2 раза, с Внутри Такта;Архитектура Хасвелла
Если бы были какие-либо сомнения в том, насколько важно максимально эффективно использовать кэш, эта презентация by Cliff Click, ранее принадлежавший Azul, должен развеять все сомнения.По его словам, "память - это новый диск!".
ОБНОВЛЕНИЕ II:Технические характеристики производительности кэша SkyLake значительно улучшены.
Вы смотрите на потребительские характеристики, а не на спецификации разработчика. Вот документация, которая вам нужна. Размеры кэша зависят от подмоделей семейства процессоров, поэтому их обычно нет в руководствах по разработке IA-32, но вы можете легко найти их в NewEgg и подобных.
Редактировать: Более конкретно:Глава 10 тома 3A (Руководство по системному программированию), глава 7 справочного руководства по оптимизации и, возможно, что-то из руководства по кэшированию страниц TLB, хотя я бы предположил, что это дальше от L1, чем вас волнует.
Я провел еще кое-какое расследование.В ETH Zurich есть группа, которая построила инструмент оценки производительности памяти который мог бы получить информацию, по крайней мере, о размере (и, возможно, также ассоциативности) кэшей L1 и L2.Программа работает, экспериментально пробуя различные схемы считывания и измеряя результирующую пропускную способность.Упрощенная версия была использована для популярный учебник Брайанта и О'Халларона.
Кэши L1 существуют на этих платформах.Это почти наверняка останется верным до тех пор, пока скорости памяти и фронтальной шины не превысят скорость процессора, а до этого, скорее всего, еще далеко.
В Windows вы можете использовать Getlogicalprocessorинформация чтобы получить некоторый уровень информации о кэше (размер, размер строки, ассоциативность и т.д.) Версия Ex на Win7 предоставит еще больше данных, например, какие ядра используют какой кэш. Процессор также предоставляет эту информацию.
Местоположение ссылки оказывает существенное влияние на производительность некоторых алгоритмов;Очевидно, что размер и скорость кэша L1, L2 (и на более новых процессорах L3) играют в этом большую роль.Умножение матриц является одним из таких алгоритмов.
Руководство Intel Vol.2 задает следующую формулу для вычисления размера кэша:
Это Размер кэша в Байтах
= (Пути + 1) * (Разделы + 1) * (Line_Size + 1) * (Наборы + 1)
= (EBX[31:22] + 1) * ( EBX[21:12] + 1) * ( EBX[11:0] + 1) * ( ECX + 1)
Где находится Ways
, Partitions
, Line_Size
и Sets
запрашиваются с помощью cpuid
с eax
установить на 0x04
.
Предоставление объявления файла заголовка
x86_cache_size.h
:
unsigned int get_cache_line_size(unsigned int cache_level);
Реализация выглядит следующим образом:
;1st argument - the cache level
get_cache_line_size:
push rbx
;set line number argument to be used with CPUID instruction
mov ecx, edi
;set cpuid initial value
mov eax, 0x04
cpuid
;cache line size
mov eax, ebx
and eax, 0x7ff
inc eax
;partitions
shr ebx, 12
mov edx, ebx
and edx, 0x1ff
inc edx
mul edx
;ways of associativity
shr ebx, 10
mov edx, ebx
and edx, 0x1ff
inc edx
mul edx
;number of sets
inc ecx
mul ecx
pop rbx
ret
Который на моей машине работает следующим образом:
#include "x86_cache_size.h"
int main(void){
unsigned int L1_cache_size = get_cache_line_size(1);
unsigned int L2_cache_size = get_cache_line_size(2);
unsigned int L3_cache_size = get_cache_line_size(3);
//L1 size = 32768, L2 size = 262144, L3 size = 8388608
printf("L1 size = %u, L2 size = %u, L3 size = %u\n", L1_cache_size, L2_cache_size, L3_cache_size);
}