Как измерить попадания dtlb и промахи dtlb с помощью perf_event_open ()? - PullRequest
0 голосов
/ 13 апреля 2020

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

Но я не могу найти, как установить конфигурацию, чтобы получить попадания dtlb и попадания dtlb. Когда я измерил промах кеша, я сделал так:

    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    pe.config = PERF_COUNT_HW_CACHE_MISSES;

1 Ответ

1 голос
/ 15 апреля 2020

В perf нет «прямых» событий PMU, которые помогут вам измерить dTLB hits. Существуют отдельные dTLB miss события для загрузки и хранения памяти, которые вы можете увидеть, выполнив следующую команду:

sudo perf list | grep 'Hardware cache'

dTLB-load-misses                                   [Hardware cache event]
dTLB-loads                                         [Hardware cache event]
dTLB-store-misses                                  [Hardware cache event]
dTLB-stores                                        [Hardware cache event]

Значения каждого из этих событий уже упоминались здесь . Они зависят от используемой вами микроархитектуры, и это будет иметь значение при вычислении dTLB-hits.

Скажем, например, что вы ищете для выборки вхождения события dTLB-load-misses,

       pe.type = PERF_TYPE_HW_CACHE;
       pe.size = sizeof(struct perf_event_attr);
       pe.config = PERF_COUNT_HW_CACHE_DTLB <<  0 | PERF_COUNT_HW_CACHE_OP_READ <<  8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16;

и если вы хотите измерить вхождения события dTLB-loads,

       pe.type = PERF_TYPE_HW_CACHE;
       pe.size = sizeof(struct perf_event_attr);
       pe.config = PERF_COUNT_HW_CACHE_DTLB <<  0 | PERF_COUNT_HW_CACHE_OP_READ <<  8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16;

Для измерения dTLB-store-misses и dTLB-stores вам необходимо заменить PERF_COUNT_HW_CACHE_OP_READ на PERF_COUNT_HW_CACHE_OP_WRITE in вышеуказанные конфиги.

При измерении любого из событий аппаратного кэша конфиг должен всегда иметь форму -

pe.config = (perf_hw_cache_id << 0) | (perf_hw_cache_op_id << 8) | (perf_hw_cache_op_result_id << 16) 

, где значения и различные «нумерованные» значения perf_hw_cache_id, perf_hw_cache_op_id и perf_hw_cache_op_result_id здесь упоминаются здесь .

В идеале, в зависимости от ваших требований, вы хотите измерить все вышеперечисленные четыре события вместе для одной рабочей нагрузки, так что пример как вы можете измерить dTLB-load-misses и dTLB-loads вместе, показано ниже -

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <asm/unistd.h>
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>


struct read_format {
  uint64_t nr;
  struct {
    uint64_t value;
    uint64_t id;
  } values[];
};

int main(int argc, char* argv[]) {
  struct perf_event_attr pea;
  int fd1, fd2;
  uint64_t id1, id2;
  uint64_t val1, val2;
  char buf[4096];
  struct read_format* rf = (struct read_format*) buf;
  int i;

  memset(&pea, 0, sizeof(struct perf_event_attr));
  pea.type = PERF_TYPE_HW_CACHE;
  pea.size = sizeof(struct perf_event_attr);
  pea.config = PERF_COUNT_HW_CACHE_DTLB <<  0 | PERF_COUNT_HW_CACHE_OP_READ <<  8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16;
  pea.disabled = 1;
  pea.exclude_kernel = 1;
  pea.exclude_hv = 1;
  pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
  fd1 = syscall(__NR_perf_event_open, &pea, 0, -1, -1, 0);
  ioctl(fd1, PERF_EVENT_IOC_ID, &id1);

  memset(&pea, 0, sizeof(struct perf_event_attr));
  pea.type = PERF_TYPE_HW_CACHE;
  pea.size = sizeof(struct perf_event_attr);
  pea.config = PERF_COUNT_HW_CACHE_DTLB <<  0 | PERF_COUNT_HW_CACHE_OP_READ <<  8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16;;
  pea.disabled = 1;
  pea.exclude_kernel = 1;
  pea.exclude_hv = 1;
  pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
  fd2 = syscall(__NR_perf_event_open, &pea, 0, -1, fd1 /*!!!*/, 0);
  ioctl(fd2, PERF_EVENT_IOC_ID, &id2);


  ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
  ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);
  sleep(10);
  ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);


  read(fd1, buf, sizeof(buf));
  for (i = 0; i < rf->nr; i++) {
    if (rf->values[i].id == id1) {
      val1 = rf->values[i].value;
    } else if (rf->values[i].id == id2) {
      val2 = rf->values[i].value;
    }
  }

  printf("dTLB-loads: %"PRIu64"\n", val1);
  printf("dTLB-load-misses: %"PRIu64"\n", val2);

  return 0;

Некоторые идеи, связанные с мониторингом нескольких событий с использованием perf_event_open, упоминаются здесь , из которых выше Программа была скопирована.

...