为什么perf报告不了缓存未命中?

42
根据perf教程perf stat应使用硬件计数器报告缓存未命中情况。然而,在我的系统上(最新的Arch Linux),它没有这样做:
[joel@panda goog]$ perf stat ./hash

 Performance counter stats for './hash':

    869.447863 task-clock                #    0.997 CPUs utilized          
            92 context-switches          #    0.106 K/sec                  
             4 cpu-migrations            #    0.005 K/sec                  
         1,041 page-faults               #    0.001 M/sec                  
 2,628,646,296 cycles                    #    3.023 GHz                    
   819,269,992 stalled-cycles-frontend   #   31.17% frontend cycles idle   
   132,355,435 stalled-cycles-backend    #    5.04% backend  cycles idle   
 4,515,152,198 instructions              #    1.72  insns per cycle        
                                         #    0.18  stalled cycles per insn
 1,060,739,808 branches                  # 1220.015 M/sec                  
     2,653,157 branch-misses             #    0.25% of all branches        

   0.871766141 seconds time elapsed

我错过了什么?我已经搜索了手册和网络,但没有找到明显的答案。

编辑:我的 CPU 是英特尔 i5 2300K,如果这有关系。


这取决于您的硬件计数器。我从未使用过perf,但我使用过PAPI(http://icl.cs.utk.edu/PAPI/),可以检查可用的硬件计数器,以了解您的CPU可以获得什么。 - SamGamgee
6
尝试运行perf stat -d命令,它会报告一些缓存事件。同时查看新的perf mem工具,可以记录/报告内存事件,文档在http://www.linuxtag.org/2013/fileadmin/www.linuxtag.org/slides/Arnaldo_Melo_-_Linux__perf__tools__Overview_and_Current_Developments.e323.pdf(第10页)和http://man7.org/linux/man-pages/man1/perf-mem.1.html。 - osgx
2
osgX,perf stat -d会打开事件多路复用,有时可能会报告不正确的速率。最好每次手动选择不超过5-7个硬件事件,并仅使用perf stat -d获取此类事件的名称。Intel的另一种方法是尝试来自https://github.com/andikleen/pmu-tools的toplev.py。 - osgx
3个回答

59

在我的系统上,一个 Intel Xeon X5570 @ 2.93 GHz ,我通过明确请求这些事件,能够让 perf stat 报告高速缓存引用和未命中。

perf stat -B -e cache-references,cache-misses,cycles,instructions,branches,faults,migrations sleep 5
Performance counter stats for 'sleep 5':

         10573 cache-references                                            
          1949 cache-misses              #   18.434 % of all cache refs    
       1077328 cycles                    #    0.000 GHz                    
        715248 instructions              #    0.66  insns per cycle        
        151188 branches                                                    
           154 faults                                                      
             0 migrations                                                  

   5.002776842 seconds time elapsed

默认的事件集不包括缓存事件,与您的结果相符,我不知道为什么。

perf stat -B sleep 5

Performance counter stats for 'sleep 5':

      0.344308 task-clock                #    0.000 CPUs utilized          
             1 context-switches          #    0.003 M/sec                  
             0 CPU-migrations            #    0.000 M/sec                  
           154 page-faults               #    0.447 M/sec                  
        977183 cycles                    #    2.838 GHz                    
        586878 stalled-cycles-frontend   #   60.06% frontend cycles idle   
        430497 stalled-cycles-backend    #   44.05% backend  cycles idle   
        720815 instructions              #    0.74  insns per cycle        
                                         #    0.81  stalled cycles per insn
        152217 branches                  #  442.095 M/sec                  
          7646 branch-misses             #    5.02% of all branches        

   5.002763199 seconds time elapsed

谢谢,这很有帮助。我猜他们一定改变了默认捕获的事件集合。 - static_rtti
不错,我也觉得每次都要记录信息很奇怪...这种方法更快 :) - SamGamgee
一个问题中的问题,perf输出中的fauts计数是多少? - Elvis Teixeira
1
@ElvisTeixeira faultspage-faults 的别名,要查看所有事件列表请运行 perf list - amdn
谢谢@amdn。现在,什么是“页面错误”? - Elvis Teixeira
有没有一种方法可以获取每个函数调用的缓存未命中,就像在“perf report”中通常看到的那样? - mojo1mojo2

16
最新的源代码中,默认事件不再包含cache-missescache-references
struct perf_event_attr default_attrs[] = {

  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK      },
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES    },
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS      },
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS     },

  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES      },
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND  },
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS        },
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES       },

};

所以这个人和大多数网站都已经过时了。


4

我花了几分钟的时间来理解perf。我通过先记录再报告数据(两种都是perf工具)来发现缓存未命中。

要查看事件列表:

perf list

例如,为了检查最后一级缓存的加载未命中情况,您需要使用事件LLC-loads-misses,如下所示。
perf record -e LLC-loads-misses ./your_program

然后报告结果

perf report -v

“cache-misses”和“LLC-loads-misses”这两个perf事件有什么区别? - munikarmanish
1
我已经有一段时间没有看过这些东西了,但我认为缓存未命中包括缓存的所有级别(通常为3个级别),而LLC可能仅适用于最后一级L3,因为这是最关键的级别,如果在此级别未命中,它就会去访问内存。 - SamGamgee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接