缓存未命中 L1 < L2 < L3

use*_*954 0 caching cpu-cache perf

我有一个特定的软件,它表现出的行为是未命中率如下所示:

L1-dcache-misses < L2-misses< L3-misses
Run Code Online (Sandbox Code Playgroud)

怎么会这样呢?

未命中率是通过perf查看重新填充计数器除以每个缓存的访问总数来计算的。

Pet*_*des 6

L1-dcache-misses是L1d 缓存中丢失的所有负载的比例。

L2 未命中是先到达 L2(在 L1 中未命中)然后在 L2 中未命中的请求的比例。L3 类似。

L1d 命中不属于总 L2 访问的一部分。 (这是有道理的,因为 L2 甚至从未见过它)。

对于在小型工作集上具有良好局部性的工作负载来说,这是很正常的,但 L1d 中丢失的访问具有较差的时空局部性,并且在外部缓存中也往往会丢失。

L1d 过滤掉所有“简单”的极高局部性访问,留下 L2 和 L3 只处理“较难”的访问。您可以说,L1d 的存在是为了为最小最热的工作集提供出色的延迟(和带宽),而 L2 则试图捕获遗漏的内容。然后 L3 只能看到访问模式中“最困难”的部分。


另外,如果您使用的是 Intel CPU,请注意,perf不仅使用 mem_load_retired.l1_miss事件等;还使用事件等。它尝试使用该事件将 L1d同一行的多个未命中计数为单个未命中L1D.REPLACEMENT。LLC-loads 和 load-misses 使用OFFCORE_RESPONSE事件,而不是mem_load_retired.l3_hit/ miss。请参阅 Linux perf 如何计算缓存引用和缓存未命中事件

(对尚未准备好的同一缓存行的两个加载将共享相同的 LFB 来跟踪传入行,因此这种计算是有意义的。此外,如果我们关心触摸/错过的行而不是单个加载。但使用它L1-dcache-loads确实MEM_INST_RETIRED.ALL_LOADS计数每个负载。因此,即使是性能报告的 L1 命中率也不是真正的每条指令的 L1d 负载命中率。对于任何在 L1d 未命中中具有空间局部性的程序来说,它会更高。)