什么被认为是高速缓存中的高失误率/低命中率?

时间:2018-04-25 14:47:14

标签: linux memory memory-management perf

我一直试图在我的机器上编写一些我作为小内存测试编写的代码,并使用perf我发现:

 Performance counter stats for './MemBenchmark':

            15,980      LLC-loads                                                   
             8,714      LLC-load-misses           #   54.53% of all LL-cache hits   

      10.002878281 seconds time elapsed

基准测试的整个想法是“压力”记忆,所以在我的书中我越高,我认为错过率越高。

编辑:Perf中是否有允许将文件分析到不同部分的功能?例如如果main()包含三个for循环,是否可以单独分析每个循环以查看LLC加载未命中的数量?

1 个答案:

答案 0 :(得分:1)

请记住,LLC负载仅计算L1d和L2中错过的负载。作为总负载的一小部分(L1-dcache-loads),这可能是整个缓存层次结构的非常良好的命中率(归功于良好的局部性和/或成功的预取。)< / p>

Your CPU has a 3-level cache,所以Last Level是共享L3; L1和L2是私有的每个核心缓存。在只有2级缓存的CPU上,LLC将是L2。)

只有9k的访问必须一直到DRAM 10秒非常好。

具有如此低的LLC负载总量的低LLC命中率告诉您,您的工作负载对于大多数访问具有良好的位置,但是错过的访问通常必须一直到DRAM,并且只有一半他们可以从拥有L3缓存中受益。

相关:Cache friendly offline random read,并在Understanding perf detail when comparing two different implementations of a BFS algorithm上查看@ BeeOnRope的答案,其中他说 LLC未命中的绝对数量是性能的重要因素。

具有较差局部性的算法将产生L2未命中的批次,并且通常会有很多L3命中(很可能具有高L3命中率),但也有很多L3未命中,所以管道很多时候都在停滞等待记忆。

  

您可以建议衡量我的计划在压力记忆方面的表现如何?

您想知道您的程序导致的总内存流量,包括预取吗?即它可能对其他竞争内存带宽的程序产生什么样的影响? offcore_requests.all_requests可以告诉您有多少请求(包括L2预取,页面遍历以及加载和存储,但不包括L3预取)使其超过L2到共享L3缓存,无论它们是否在共享L3中命中。 (perf LLC-load-misses。我的Skylake有此事件; IDK如果您的Nehalem会。)

至于检测你的代码是否存在内存瓶颈,每秒cycle_activity.stalls_l3_miss作为绝对量度是合理的。 Skylake至少有一个perf record -e whatever计数周期,没有执行uops,并且有一个未完成的L3未命中。如果这超过总周期的几个百分点,那么您需要考虑避免这些停滞。

(我没有尝试过使用这些活动自己学习任何东西,但它们可能不是最有用的建议。在分析时很难知道正确的问题;有很多事件你可以看一下,但是用它们来学习一些东西可以帮助你弄清楚如何改变你的代码很难。很好地了解你的代码如何使用内存,所以你知道要寻找什么。一般问题,很难说太多。)

  

有没有一种方法可以建议可以分解基准文件以查看哪些循环导致的压力最大?

您可以使用perf report -Mintel / func shell(_ command: String) -> String { let task = Process() task.launchPath = "/bin/bash" task.arguments = ["-c", command] let pipe = Pipe() task.standardOutput = pipe task.launch() let data = pipe.fileHandleForReading.readDataToEndOfFile() let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String return output } // Example usage: shell("ls -la") 为您想要的任何事件进行基于统计样本的分析,以查看热点的位置。

但是对于缓存未命中,有时 blame 会出现一些代码,这些代码循环遍历一个数组并驱逐了大量有价值的数据,而不是那些触及仍然很热的有价值数据的代码。

如果硬件预取能够完成其工作,那么大数组上的循环可能看不到很多缓存未命中。

<强> Use the ocperf.py wrapper 即可。如果您不确切知道程序中的速度和速度,那么使用堆栈采样可能非常非常有用。在每个事件上对调用堆栈进行采样将向您显示调用树中哪个函数调用高达其被调用者正在执行的所有工作。首先避免该调用可能比加快它调用的函数要好得多。

(避免工作,而不是仅仅使用更好的蛮力做同样的工作。现代CPU可以为AVX2带来的最大暴力的小心应用是非常有用的在你之后确定你不能在一开始就避免这样做。)