请记住,LLC-loads 仅计算 L1d 和 L2 中丢失的负载。作为总负载 (L1-dcache-loads) 的一小部分,这可能是整个缓存层次结构的非常良好的命中率(这要归功于良好的局部性和/或成功的预取。)
(Your CPU has a 3-level cache,所以最后一级是共享的 L3;L1 和 L2 是每个核心的私有缓存。在只有 2 级缓存的 CPU 上,LLC 是 L2。)
只有 9k 次访问必须一直到 DRAM 10 秒是非常非常好的。
LLC 总负载如此之低的低 LLC 命中率告诉您,您的工作负载对于其大部分访问具有良好的局部性,但未命中的访问通常必须一直到达 DRAM,并且只有一半他们完全受益于 L3 缓存。
相关:Cache friendly offline random read,并查看@BeeOnRope 在Understanding perf detail when comparing two different implementations of a BFS algorithm 上的回答,他说LLC 未命中的绝对数量是性能的重要因素。
局部性较差的算法会产生很多的 L2 未命中,并且通常会产生很多 L3 命中(很可能具有高 L3 命中率),但也会产生很多总的 L3 未命中,因此管道在等待内存的时间很多。
您建议用什么指标来衡量我的程序在强调内存方面的表现?
您想知道您的程序导致的总内存流量(包括预取)吗?即它可能对其他竞争内存带宽的程序产生什么样的影响? offcore_requests.all_requests 可以告诉您有多少请求(包括 L2 预取、页面遍历以及加载和存储,但不包括 L3 预取)通过 L2 到达共享 L3 缓存,无论它们是否在共享 L3 中命中。 (Use the ocperf.py wrapper for perf。我的 Skylake 有那个活动;如果你的 Nehalem 愿意,IDK。)
就检测您的代码是否存在内存瓶颈而言,以每秒LLC-load-misses 作为绝对衡量标准是合理的。 Skylake 至少有一个 cycle_activity.stalls_l3_miss 来计算没有执行 uops 并且有一个突出的 L3 未命中的周期。如果这超过总周期的百分之几,您需要考虑避免这些停顿。
(我自己没有尝试使用这些事件来学习任何东西,它们可能不是最有用的建议。在分析时很难知道要问自己的正确问题;有很多事件可以查看,但使用他们学习一些可以帮助您弄清楚如何更改代码的东西很难。对代码如何使用内存有一个很好的心理了解很有帮助,因此您知道要寻找什么。对于这样一个一般性的问题,很难多说。)
您是否可以建议一种方法来分解基准文件以查看哪些循环造成的压力最大?
您可以使用perf record -e whatever / perf report -Mintel 对您想要的任何事件进行基于统计样本的分析,以查看热点在哪里。
但是对于缓存未命中,有时责备在于一些循环遍历数组并驱逐大量有价值数据的代码,而不是涉及仍然很热的有价值数据的代码。
如果硬件预取完成它的工作,一个大数组上的循环可能不会看到很多缓存未命中。
linux perf: how to interpret and find hotspots。如果您不确切知道程序中什么是慢速和快速,则使用堆栈采样可能非常有用。对每个事件的调用堆栈进行采样将显示调用树中的哪个函数调用应为其被调用者所做的所有工作负责。一开始就避免该调用比稍微加快它调用的函数要好得多。
(避免工作,而不仅仅是用更好的蛮力做同样的工作。仔细应用现代 CPU 可以承受 AVX2 的最大蛮力是有用的你已经确定你一开始就无法避免这样做。)