首先,包容性缓存层次结构可能并不像您假设的那么常见.例如,我不认为任何当前的英特尔处理器 - 不是Nehalem,而不是Sandybridge,可能是Atoms--都有一个L1包含在L2中.(然而,Nehalem和Sandybridge确实将L1和L2都包含在L3中;使用英特尔目前的术语,LLC中的FLC和MLC.)
但是,这不一定重要.在大多数缓存层次结构中,如果您有L1缓存未命中,那么可能会在L2中查找该未命中.无论是否具有包容性都无关紧要.如果不这样做,你必须要有一些东西告诉你,你关心的数据(可能)不在L2中,你不需要看.虽然我已经设计了这样做的协议和内存类型 - 例如只在L1而不是L2中缓存的内存类型,对于像图形这样的东西很有用,你可以在L1中获得组合的好处,但是你反复扫描的地方一个大型数组,所以L2中的缓存不是一个好主意.有点我不知道有人正在运送它们.
无论如何,这里有一些原因可以解释为什么L1高速缓存未命中的数量可能不等于L2高速缓存访问的数量.
您没有说明您正在使用的系统 - 我知道我的答案适用于Nehalem和Sandybridge等Intel x86,其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]的地址等于零模64,那么A [0] .. A [63]将在具有64字节高速缓存行的机器上的同一高速缓存行中.如果使用它们的代码很简单,很可能所有这些都可以推测性地发布.QED:64个推测性内存访问,64个L1缓存未命中,但只有一个L2内存访问.
(顺便说一句,不要指望数字非常干净.每次L2访问可能无法获得64次L1访问.)
更多可能性:
如果L2访问次数大于L1缓存未命中数(我几乎从未见过它,但有可能),则可能存在令硬件预取混淆的内存访问模式.硬件预取程序尝试预测您将需要哪些缓存行. 如果预取程序预测错误,它可能会获取您实际不需要的缓存行. 通常,有一个表现不计算Prefetches_from_L2或Prefetches_from_Memory.
某些机器可能会在将它们发送到L2之前取消导致L1缓存未命中的推测访问.但是,我不知道英特尔会这样做.