我正在学习CPU缓存,现在我仍然对缓存一致性协议(MESI)有误解。想象一下,我们有2个内核在共享状态下有一个缓存行。其中一个执行读取,另一个执行写入:
;mem is cached in Shared state
Thread 1 (core 1) Thread 2 (core 2)
mov rax, [mem] mov [mem], dword 1
核心1可以观察到一些中间状态。我的意思是以下内容:
Core 2
将L1D
中的缓存行标记为已修改,并将更改写入其中。core 1
的{{1}}缓存中的缓存行仍处于L1D
状态,因此读取时会读取陈旧值。Shared
的{{1}}缓存中的行被标记为无效。在英特尔的MESI / MESIF实施中是否有可能出现这种情况?
答案 0 :(得分:4)
核心1的L1D缓存中的缓存行仍处于共享状态
这是违反MESI的情景的一部分。商店无法提交,直到核心2发送的RFO完成,因此核心1的线路处于无效状态。
在你的例子中,它不会真正成为一个"中间体"尽管如此。如果没有同步,就无法区分您的不可能场景,只需在线路无效之前完成核心1的负载。即核心1的负载可以在核心2以全局顺序存储之前出现。
商店在本地执行之前不会全局可见(他们必须退休,然后商店队列可以将它们提交给L1D),x86的内存模型允许StoreLoad重新排序,因此商店可以被延迟(保持隐藏在私人商店队列中),直到核心2的后续加载变为全局可见。 (有关内存重新排序的更多背景知识以及StoreLoad重新排序的含义,请参阅Jeff Preshing的Memory Barriers Are Like Source Control Operations。)
在MESI(以及所有变体,如MESIF或MOESI)中,如果一个缓存的行处于E或M状态,则没有其他缓存可以拥有该行的副本。 the MESI wikipedia article中的状态表非常清楚:如果一个缓存具有E或M状态,则其他缓存都具有无效。
两个缓存都不可能同时拥有具有不同数据的行的有效副本。这就是缓存一致的意义,阻止它发生是MESI协议的重点。
如果核心想要修改缓存行,则需要对该行进行独占所有权,以便其他核心无法观察到过时的值。这必须在之前发生商店可以提交到L1D。存在存储队列以隐藏“所有权读取”的延迟(以及其他内容),但存储队列中的数据尚未提交给L1D。 (相关:What happens when different CPU cores write to the same RAM address without synchronization?有更多关于商店队列的信息。)
而BTW,让我们假设[mem]
是自然对齐的,因此对它的加载/存储是原子的(由x86架构保证)。 Why is integer assignment on a naturally aligned variable atomic on x86?
多级缓存和修改后的行
对于多级缓存,脏缓存行可以在层次结构中向上传播。因此,一行可以在L1D中处于修改状态,而在同一核心中可以处于L2 。这很好,因为来自L1D的回写通过L2。
据我了解,Intel CPU中共享的包容性L3缓存在将高速缓存行的副本共享到多个核心之前不必回写到DRAM。因此,就普通/简单的MESI而言,将L3视为后备存储,而不是DRAM。
在多插槽系统上进行此工作非常棘手;我不确定是否已设置好所以套接字中的L3只能缓存与连接到该套接字的DRAM对应的物理地址。在任何情况下,侦听请求都是在L3缓存未命中的套接字之间发送的,并且您可以配置许多复杂的设置以在Xeon系统上进行调整。 (例如,请参阅an Anandtech article about Haswell Xeon。)
答案 1 :(得分:2)
在步骤1,核心2之前的可以将该行标记为已修改,它必须通知核心1.因此,在步骤2,该行不再位于核心1 L1D中。因此,在第2步,在访问该行之前,核心1必须从核心2获得更新的值。