【问题标题】:How to measure the dtlb hits and dtlb misses with perf_event_open()?如何使用 perf_event_open() 测量 dtlb 命中和 dtlb 未命中?
【发布时间】:2020-07-26 03:19:36
【问题描述】:

我想测量缓存未命中率和 dtlb 未命中率。 我已经完成了第一部分。

但我找不到如何设置配置以获取 dtlb 未命中和 dtlb 命中。 当我测量缓存未命中时,我是这样的:

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

【问题讨论】:

    标签: perf tlb intel-pmu


    【解决方案1】:

    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]
    

    here 已经提到了每个事件的含义。它们取决于您使用的微架构,这对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-missesdTLB-stores,您需要在上述配置中将PERF_COUNT_HW_CACHE_OP_READ 替换为PERF_COUNT_HW_CACHE_OP_WRITE

    在测量任何硬件缓存事件时,配置应始终采用以下形式 -

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

    perf_hw_cache_idperf_hw_cache_op_idperf_hw_cache_op_result_id 的含义和不同的“枚举”值被提及here

    理想情况下,根据您的要求,您希望针对单个工作负载同时测量上述所有四个事件,因此下面显示了如何一起测量 dTLB-load-missesdTLB-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 监控多个事件时涉及的一些想法提到了here,上面的程序已从中复制。

    【讨论】:

      猜你喜欢
      • 2013-07-31
      • 2012-08-26
      • 2019-10-03
      • 2019-02-04
      • 1970-01-01
      • 1970-01-01
      • 2021-01-12
      • 2012-02-17
      • 1970-01-01
      相关资源
      最近更新 更多