当L1缓存未命中与L2访问差异很大时...与TLB有关吗?

6
我一直在对一些算法进行基准测试,并分析它们的内存使用和效率(L1/L2/TLB访问和缺失),其中一些结果对我来说非常有趣。
考虑到包含L1和L2缓存的层次结构,L1缓存缺失的数量不应该与L2缓存访问的数量相一致吗?我发现其中一个解释可能与TLB相关:当虚拟地址未映射到TLB时,系统会自动跳过某些缓存级别的搜索。这种情况是否合理?
2个回答

10
首先,包容性高速缓存层次结构可能并不像你想象的那么常见。例如,我认为任何现有的英特尔处理器 - 不论是 Nehalem,还是 Sandybridge,甚至是 Atom 系列的处理器 - 都没有 L1 包含在 L2 中。(然而,Nehalem 和可能的 Sandybridge 处理器却同时将 L1 和 L2 包含在 L3 中;使用英特尔的当前术语,FLC 和 MLC 在 LLC 中。)
但是,这并不一定重要。在大多数高速缓存层次结构中,如果 L1 缓存未命中,则该未命中可能会在 L2 中查找。无论它是包容性的还是非包容性的都没有关系。如果要做到相反,您需要有某些东西来告诉您所关心的数据(可能)不在 L2 中,您不需要查找。虽然我设计过可以做到这一点的协议和内存类型 - 例如只在 L1 中缓存但不在 L2 中缓存的内存类型,对于诸如图形之类的内容非常有用,其中您可以获得组合在 L1 中的好处,但是当您不断扫描大型数组时,在 L2 中进行缓存并不是一个好主意。但我目前不知道有人正在运送它们。
无论如何,以下是一些原因,说明为什么 L1 缓存未命中的数量可能不等于 L2 缓存访问的数量。
您没有说明您正在使用哪些系统-我知道我的答案适用于 Intel x86,例如 Nehalem 和 Sandybridge,它们的 EMON 性能事件监视允许您计算诸如 L1 和 L2 缓存未命中等内容。它可能还适用于具有硬件性能计数器的现代微处理器,例如 ARM 和 Power 上的那些处理器。
大多数现代微处理器不会在第一个缓存未命中处停止,并继续尝试额外的工作。这总体上通常称为推测执行。此外,处理器可能是按顺序或乱序的,但即使是前者,也可能会导致 L1 未命中次数和 L2 访问次数之间的差异更大,这并不是必需的。简短回答:这些投机性内存访问中很多会访问同一内存位置。它们会被压缩并合并。
性能事件“L1高速缓存未命中”可能计算的是错过L1高速缓存的(投机)指令数量,随后分配硬件数据结构,在英特尔称为填充缓冲区,在其他地方称为未命中状态处理寄存器。随后对相同缓存行的后续高速缓存未命中会错过L1高速缓存但会击中填充缓冲区,并被压缩。其中只有一个,通常是第一个,会发送到L2,视为L2访问次数。此外,可能存在一个性能事件:Squashed_Cache_Misses。也可能存在性能事件L1_Cache_Misses_Retired,但这可能低估结果,因为投机执行可能将数据拉入缓存,而退役时的缓存未命中可能永远不会发生。
例如,假设正在访问字节A[0]、A[1]、A[2],... A[63]、A[64],...
如果A[0]的地址等于64的倍数,则A[0]..A[63]将位于同一个缓存行中,在具有每个缓存行64字节大小的机器上。如果使用这些代码的过程很简单,那么所有这些代码都可以被投机地执行。因此会有64个投机性内存访问,64个L1缓存未命中,但只有一个L2内存访问。顺证毕立。
(顺便说一下,不要期望数字完全如此整洁。你可能无法确切地获得每个L2访问的64个L1访问次数)。
以下是更多可能性:如果L2访问次数大于L1缓存未命中的次数(我几乎从未见过,但这是可能的),那么您可能有一个混淆了硬件预取器的内存访问模式。硬件预取器试图预测您将需要哪些缓存行。如果预取器预测错误,它可能会获取您实际上不需要的缓存行。通常,有性能事件计算Prefetches_from_L2或Prefetches_from_Memory。
有些机器可能会在发送到L2之前取消已经导致L1缓存未命中的推测性访问。然而,我不知道英特尔是否会这样做。

1
堆叠:您可能正在查看像L1_DCACHE_MISSES_RETIRED这样的性能计数器事件。有可能错误的路径指令触发了L1和/或L2缓存填充 - 因此您可能永远不会看到L2“退役”缓存未命中。 - Krazy Glew

2
数据缓存的写入策略决定了存储命中是否仅在该缓存上进行数据写入(写回或复制回)或者也在缓存层次结构的下一级进行写入(写穿透)。 因此,在写穿透L1-D缓存的存储器也会将其数据写入L2缓存。 这可能是来自L1缓存未命中的L2访问的另一个来源。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接