Аппаратный кеш событий и перф
Когда я бегу perf list
Я вижу кучу событий Hardware Cache следующим образом:
$ perf list | grep 'cache event'
L1-dcache-load-misses [Hardware cache event]
L1-dcache-loads [Hardware cache event]
L1-dcache-stores [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
LLC-load-misses [Hardware cache event]
LLC-loads [Hardware cache event]
LLC-store-misses [Hardware cache event]
LLC-stores [Hardware cache event]
branch-load-misses [Hardware cache event]
branch-loads [Hardware cache event]
dTLB-load-misses [Hardware cache event]
dTLB-loads [Hardware cache event]
dTLB-store-misses [Hardware cache event]
dTLB-stores [Hardware cache event]
iTLB-load-misses [Hardware cache event]
iTLB-loads [Hardware cache event]
node-load-misses [Hardware cache event]
node-loads [Hardware cache event]
node-store-misses [Hardware cache event]
node-stores [Hardware cache event]
Похоже, что эти события в основном возвращают разумные значения, основанные на тестах, но я хотел бы знать, как определить, чтобы сопоставить эти события с событиями счетчика производительности оборудования в моей системе?
То есть эти события, безусловно, реализуются с использованием одного или нескольких базовых счетчиков x86 PMU на моем процессоре Skylake - но как узнать, какие из них?
Вы можете посмотреть в /sys/devices/cpu/events
для других аппаратных событий, но не для "Аппаратных событий кэша".
1 ответ
Пользователь @Margaret указывает на разумный ответ в комментариях - прочитайте исходный код ядра, чтобы увидеть отображение событий PMU.
Мы можем проверить arch/x86/events/intel/core.c для определения событий. На самом деле я не знаю, относится ли "ядро" к архитектуре Core, просто это ядро подходит для большинства определений, но в любом случае это файл, который вы хотите посмотреть.
Ключевой частью является этот раздел, который определяет skl_hw_cache_event_ids
:
static __initconst const u64 skl_hw_cache_event_ids
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
{
[ C(L1D ) ] = {
[ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_INST_RETIRED.ALL_LOADS */
[ C(RESULT_MISS) ] = 0x151, /* L1D.REPLACEMENT */
},
[ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_INST_RETIRED.ALL_STORES */
[ C(RESULT_MISS) ] = 0x0,
},
[ C(OP_PREFETCH) ] = {
[ C(RESULT_ACCESS) ] = 0x0,
[ C(RESULT_MISS) ] = 0x0,
},
},
...
Расшифровывая вложенные инициализаторы, вы получаете, что L1D-dcahe-load
соответствует MEM_INST_RETIRED.ALL_LOAD
а также L1-dcache-load-misses
в L1D.REPLACEMENT
,
Мы можем проверить это дважды с помощью perf:
$ ocperf stat -e mem_inst_retired.all_loads,L1-dcache-loads,l1d.replacement,L1-dcache-load-misses,L1-dcache-loads,mem_load_retired.l1_hit head -c100M /dev/zero > /dev/null
Performance counter stats for 'head -c100M /dev/zero':
11,587,793 mem_inst_retired_all_loads
11,587,793 L1-dcache-loads
20,233 l1d_replacement
20,233 L1-dcache-load-misses # 0.17% of all L1-dcache hits
11,587,793 L1-dcache-loads
11,495,053 mem_load_retired_l1_hit
0.024322360 seconds time elapsed
События "Аппаратного кэша" показывают те же значения, что и при использовании базовых событий PMU, о которых мы догадались, проверив источник.