解释perf属性输出

时间:2015-03-14 07:12:52

标签: performance caching optimization computer-architecture perf

我开发了一个代码,可以输入大型二维图像(最高64MP像素)和:

  • 在每行上应用过滤器
  • 转置图像(使用阻止以避免大量缓存未命中)
  • 对图像的列(现在行)应用过滤器
  • 将过滤后的图像转换回来继续进行其他计算

虽然它没有改变,但为了完整我的问题,过滤是应用离散小波变换,代码用C语言编写。

我的最终目标是尽可能快地运行。到目前为止,通过使用阻塞矩阵转置,矢量化,多线程,编译器友好的代码等,我的速度提高了10倍以上。

来到我的问题:我所拥有的代码的最新分析统计数据(使用perf stat -e)让我感到困扰。

        76,321,873 cache-references                                            
     8,647,026,694 cycles                    #    0.000 GHz                    
     7,050,257,995 instructions              #    0.82  insns per cycle        
        49,739,417 cache-misses              #   65.171 % of all cache refs    

       0.910437338 seconds time elapsed

(缓存未命中数)/(#指令)低约0.7%。 Here提到这个数字是检查内存效率的好事。

另一方面,高速缓存未命中缓存引用的百分比非常高(65%!),正如我所看到的那样,可以表明执行在缓存效率方面出现问题。

perf stat -d的详细统计信息是:

   2711.191150 task-clock                #    2.978 CPUs utilized          
         1,421 context-switches          #    0.524 K/sec                  
            50 cpu-migrations            #    0.018 K/sec                  
       362,533 page-faults               #    0.134 M/sec                  
 8,518,897,738 cycles                    #    3.142 GHz                     [40.13%]
 6,089,067,266 stalled-cycles-frontend   #   71.48% frontend cycles idle    [39.76%]
 4,419,565,197 stalled-cycles-backend    #   51.88% backend  cycles idle    [39.37%]
 7,095,514,317 instructions              #    0.83  insns per cycle        
                                         #    0.86  stalled cycles per insn [49.66%]
   858,812,708 branches                  #  316.766 M/sec                   [49.77%]
     3,282,725 branch-misses             #    0.38% of all branches         [50.19%]
 1,899,797,603 L1-dcache-loads           #  700.724 M/sec                   [50.66%]
   153,927,756 L1-dcache-load-misses     #    8.10% of all L1-dcache hits   [50.94%]
    45,287,408 LLC-loads                 #   16.704 M/sec                   [40.70%]
    26,011,069 LLC-load-misses           #   57.44% of all LL-cache hits    [40.45%]

   0.910380914 seconds time elapsed

此处前端和后端停滞的周期也很高,而较低级别的缓存似乎遭受57.5%的高失误率。

哪种指标最适合此方案?我想到的一个想法是,可能是工作量不再需要进一步“触摸”的情况。在初始图像加载之后的LL缓存(加载值一次,之后它完成 - 工作负载比内存绑定更多是CPU绑定的图像过滤算法)。

我运行它的机器是Xeon E5-2680(20M智能缓存,其中每个核心有256KB L2缓存,8个核心)。

1 个答案:

答案 0 :(得分:3)

首先要确保您的计算机上正在运行没有其他计算密集型进程。那是一个服务器CPU所以我认为这可能是一个问题。

如果在程序中使用多线程,并且在线程之间分配相同数量的工作,则可能会感兴趣仅在一个CPU上收集指标

我建议在优化阶段禁用超线程,因为在解释性能分析指标时会导致混淆。 (例如,在后端花费的#cycles增加了)。此外,如果你将工作分配给3个线程,你很有可能2个线程将共享一个核心的资源,而第3个线程将拥有整个核心 - 它会更快。

Perf从未擅长解释指标。根据数量级来判断,缓存引用是命中LLC的L2未命中。如果LLC引用/ #Instructions的数量很少,则与LLC引用相比较高的LLC未命中数并不总是坏事。在您的情况下,您有0.018,这意味着您的大部分数据都是从L2使用的。高LLC错失率意味着您仍然需要从RAM获取数据并将其写回。

关于#Cycles BE和FE绑定,我有点担心这些值,因为它们不会总和到100%和总周期数。你有8G,但在BE的FE和4G周期中保持6G周期。这似乎不太正确。

如果FE周期很高,则表示您在指令缓存或错误的分支推测中未命中。如果BE周期很高,则表示您等待数据。

无论如何,关于你的问题。评估代码性能的最相关指标是指令/周期(IPC)。您的CPU最多可以执行4条指令/周期。你只执行0.8。这意味着资源未得到充分利用,除非您有许多向量指令。在IPC之后,您需要检查分支未命中和L1未命中(数据和代码),因为这些会产生最多的惩罚。

最后的建议:您可能有兴趣尝试使用英特尔的vTune放大器。它可以更好地解释指标并指出代码中的最终问题。