Я пытаюсь отслеживать события кэша при выполнении определенной рабочей нагрузки C.
В частности, я пытаюсь измерить количество ссылок на кеш и кеша пропускания на всех уровнях кэша (независимо от того, вызваны ли они на загрузке или в магазине). События: < /p>
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]
node-load-misses [Hardware cache event]
node-loads [Hardware cache event]
node-store-misses [Hardware cache event]
node-stores [Hardware cache event]
< /code>
, а также эти другие события, связанные с кэшем: < /p>
cache-misses [Hardware event]
cache-references [Hardware event]
< /code>
Мой первый вопрос: что именно измерения кэша, ссылки на кеш? Почему они не перечислены как кэш -события? Я интегрировал его в свой код следующим образом: < /p>
- Определения фонов: < /li>
< /ol>
#define NUM_EVENTS 9
const char *events[NUM_EVENTS] = {
"L1-dcache-loads",
"L1-dcache-stores",
"L1-dcache-load-misses",
"LLC-loads",
"LLC-stores",
"LLC-load-misses",
"LLC-store-misses",
"cache-references",
"cache-misses"
};
enum event_num {
L1_CACHE_LOADS,
L1_CACHE_STORES,
L1_CACHE_MISSES,
L3_CACHE_LOADS,
L3_CACHE_STORES,
L3_CACHE_LOAD_MISSES,
L3_CACHE_STORE_MISSES,
CACHE_REFS,
CACHE_MISSES
};
< /code>
Настройка:
прямо перед моей фактической рабочей нагрузкой начнет работать-< /li>
< /ol>
int fds[NUM_EVENTS];
unsigned long counts[NUM_EVENTS];
struct perf_event_attr pe[NUM_EVENTS];
pfm_initialize();
for (i = 0; i < NUM_EVENTS; i++) {
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.size = sizeof(struct perf_event_attr);
pe.type = PERF_TYPE_RAW;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
pfm_perf_encode_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.attr = &pe;
if (pfm_get_os_event_encoding(events, PFM_PLM3, PFM_OS_PERF_EVENT, &arg) != PFM_SUCCESS) {
fprintf(stderr, "Error encoding event %s\n", events);
exit(1);
}
fds = perf_event_open(&pe[i], 0, -1, -1, 0);
if (fds[i] == -1) {
perror("perf_event_open failed");
exit(1);
}
}
for (i = 0; i < NUM_EVENTS; i++) ioctl(fds[i], PERF_EVENT_IOC_RESET, 0);
for (i = 0; i < NUM_EVENTS; i++) ioctl(fds[i], PERF_EVENT_IOC_ENABLE, 0);
< /code>
Подсчет и очистка:
После завершения рабочей нагрузки-< /li>
< /ol>
for (i = 0; i < NUM_EVENTS; i++) ioctl(fds[i], PERF_EVENT_IOC_DISABLE, 0);
for (i = 0; i < NUM_EVENTS; i++) read(fds[i], &counts[i], sizeof(uint64_t));;
L1_cache_accesses = counts[L1_CACHE_LOADS] + counts[L1_CACHE_STORES];
L1_cache_misses = counts[L1_CACHE_MISSES];
L3_cache_accesses = counts[L3_CACHE_LOADS] + counts[L3_CACHE_STORES];
L3_cache_misses = counts[L3_CACHE_LOAD_MISSES] + counts[L3_CACHE_STORE_MISSES];
cache_accesses = counts[CACHE_REFS];
cache_misses = counts[CACHE_MISSES];
for (i = 0; i < NUM_EVENTS; i++) close(fds[i]);
< /code>
Этот код работает относительно хорошо (в том смысле, что он компилирует и не срабатывает;)), но иногда результаты, которые он генерирует, являются странными. В частности, в некоторых случаях он сообщает о большем количестве промахов кэша L1, чем доступа к кешу L1, что заставляет меня поверить, что я сделал что-то не так. L1_CACHE_ACCESSES AS L1-DCACHE-LADS+L1-DCACHE-STORES и L1_CACHE_MISSES AS L1-DCACHE-LOADS (Учитывая, что мне не волнует кеш инструкций)? Если нет, то какие события PERF будут лучше отражать их? Если нет, то какие события PERF лучше отражают их?
Большое спасибо за вашу помощь!
Подробнее здесь: https://stackoverflow.com/questions/794 ... ing-libpfm
Мобильная версия