7

我一直在对一些算法运行一些基准测试并分析它们的内存使用和效率(L1/L2/TLB 访问和未命中),其中一些结果对我来说非常有趣。

考虑到包容性缓存层次结构(L1 和 L2 缓存),L1 缓存未命中的数量不应该与L2 缓存访问 的数量一致吗?我发现的一种解释与 TLB 相关:当虚拟地址未映射到 TLB 中时,系统会自动跳过某些缓存级别中的搜索。这看起来合法吗?

4

2 回答 2

11

首先,包容性缓存层次结构可能不像您想象的那么普遍。例如,我不认为任何当前的英特尔处理器——不是 Nehalem,不是 Sandybridge,可能是 Atoms——都有一个包含在 L2 中的 L1。(不过,Nehalem 和可能 Sandybridge 确实将 L1 和 L2 都包含在 L3 中;使用英特尔当前的术语,LLC 中的 FLC 和 MLC。)

但是,这并不一定重要。在大多数缓存层次结构中,如果您有一个 L1 缓存未命中,那么该未命中可能会在 L2 中查找。是否包容都无所谓。否则,您必须有一些东西告诉您您关心的数据(可能)不在 L2 中,您无需查看。尽管我已经设计了执行此操作的协议和内存类型 - 例如,一种仅缓存在 L1 而不是 L2 中的内存类型,对于像图形这样的东西很有用,您可以获得在 L1 中组合的好处,但您会反复扫描一个大数组,所以在 L2 中缓存不是一个好主意。位我目前不知道有人运送它们。

无论如何,这里有一些原因导致 L1 缓存未命中次数可能不等于 L2 缓存访问次数。

您没有说您正在使用什么系统 - 我知道我的回答适用于英特尔 x86,例如 Nehalem 和 Sandybridge,其 EMON 性能事件监控允许您计算 L1 和 L2 缓存未命中等内容。它可能会也适用于任何具有缓存未命中硬件性能计数器的现代微处理器,例如 ARM 和 Power 上的微处理器。

大多数现代微处理器不会在第一次缓存未命中时停止,而是继续尝试做额外的工作。这通常被称为推测执行。此外,处理器可能是有序的或无序的,但尽管后者可能会让您在 L1 未命中数和 L2 访问数之间产生更大的差异,但这不是必需的 - 即使在 -订单处理器。

简短的回答:这些推测性内存访问中的许多都将访问相同的内存位置。它们将被压扁并合并。

性能事件“L1 缓存未命中”可能是 [*] 计算错过 L1 缓存的(推测)指令的数量。然后分配一个硬件数据结构,在英特尔称为填充缓冲区,在其他一些地方分配一个未命中状态处理寄存器。到同一高速缓存行的后续高速缓存未命中将未命中 L1 高速缓存但命中填充缓冲区,并且将被压缩。只有其中一个,通常是第一个将被发送到 L2,并计为 L2 访问。)

顺便说一句,可能有一个性能事件:Squashed_Cache_Misses。

也可能存在性能事件 L1_Cache_Misses_Retired。但这可能低估了,因为推测可能会将数据拉入缓存,并且可能永远不会发生退休时的缓存未命中。

([*] 顺便说一句,当我在这里说“可能”时,我的意思是“在我帮助设计的机器上”。几乎可以肯定。我可能需要检查定义,查看 RTL,但如果不。几乎可以保证。)

例如,假设您正在访问字节 A[0], A[1], A[2], ... A[63], A[64], ...

如果 A[0] 的地址等于 0 模 64,则 A[0]..A[63] 将在同一缓存行中,在具有 64 字节缓存行的机器上。如果使用这些的代码很简单,那么很可能所有这些都可以投机发行。QED:64 次推测性内存访问,64 次 L1 缓存未命中,但只有一次 L2 内存访问。

(顺便说一句,不要指望数字会这么干净。每个 L2 访问可能无法准确获得 64 个 L1 访问。)

更多可能性:

如果 L2 访问的数量大于 L1 缓存未命中的数量(我几乎从未见过,但这是可能的),您可能有一个内存访问模式,它会混淆硬件预取器。硬件预取器尝试预测您将需要哪些缓存行。 如果预取器预测错误,它可能会获取您实际上不需要的缓存行。 经常有性能需要计算 Prefetches_from_L2 或 Prefetches_from_Memory。

某些机器可能会在将导致 L1 缓存未命中的推测性访问发送到 L2 之前取消它们。但是,我不知道英特尔这样做。

于 2012-04-28T01:26:27.700 回答
2

数据缓存的写入策略确定存储命中是仅将其数据写入该缓存(回写或回写)还是在缓存层次结构的下一级(直写)。因此,命中直写 L1-D 缓存的存储也将其数据写入 L2 缓存。

这可能是不是来自 L1 缓存未命中的 L2 访问的另一个来源。

于 2013-03-21T23:00:05.227 回答