我开发了一个代码,可以输入大型二维图像(最高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个核心)。
答案 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放大器。它可以更好地解释指标并指出代码中的最终问题。