作者:秋日里的一抹阳光_797 | 来源:互联网 | 2022-12-26 16:27
我正在学习有关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
的L1D
高速缓存仍处于Shared
状态,所以读恰好读取陈旧的价值。
读取过时的值之后,已经将core 1
的L1D
缓存中的行标记为无效。
英特尔的MESI / MESIF实施中是否可能出现这种情况?
1> Peter Cordes..:
核心1的L1D缓存中的缓存行仍处于Shared状态
这是违反MESI的方案的一部分。在核心2发送的RFO完成之前,存储无法提交,因此核心1的行处于无效状态。
但是,在您的示例中,这实际上不是“中间”步骤。如果没有同步,则无法通过将核心1的负载简单地在线路无效之前发生来区分您不可能的情况。也就是说,核心1的负载可以按全局顺序出现在核心2的存储之前。
直到在本地执行存储之后(它们必须退出,然后存储队列才能将它们提交到L1D),这些存储才成为全局可见的,并且x86的内存模型允许StoreLoad重新排序,因此可以延迟存储(保留隐藏在私有存储中)队列),直到以后核心2的负载变得全局可见。(有关内存重新排序以及StoreLoad重新排序的含义的更多信息,请参阅Jeff Preshing的“ 内存障碍就像源代码控制操作 ”。)
在MESI(以及所有类似MESIF或MOESI的变体)中,如果一个缓存的行处于E或M状态,则其他缓存都不能拥有该行的副本。MESI维基百科文章中的状态表清楚地表明了这一点:如果一个缓存具有E或M状态,则其他缓存都具有Invalid状态。
两个缓存都不可能都具有一行具有不同数据的有效副本。这就是缓存保持一致的含义,而阻止这种情况的发生是MESI协议的重点。
如果某个核心想要修改一个缓存行,它将获得该行的独占所有权,因此其他任何核心都无法观察到过时的值。这必须在商店可以提交到L1D 之前进行。存在存储队列以隐藏所有权读取的延迟(除其他事项外),但是存储队列中的数据尚未提交给L1D。(相关:当不同的CPU内核不同步地写入同一RAM地址时会发生什么?有关存储队列的更多信息)。
顺便说一句,顺便说一句,假设它[mem]
是自然对齐的,因此对其的加载/存储是原子的(由x86架构保证)。 为什么在x86上对自然对齐的可变原子进行整数赋值?。
多级缓存和修改的行
使用多级缓存,脏的缓存行可以在层次结构中传播。因此,在同一核心的 L1D和L2中,一条线可以处于修改状态。这很好,因为从L1D进行写回通过L2。
据我了解,英特尔CPU中包含共享的三级高速缓存无需先回写DRAM,即可将高速缓存行的副本共享给多个内核。因此,就普通/简单的MESI而言,将L3视为后备存储,而不是DRAM。
在多路插座系统上进行这项工作很棘手。我不确定是否已进行设置,因此套接字中的L3只能缓存与该套接字所连接的DRAM对应的物理地址。无论如何,侦听请求都会在L3缓存未命中的套接字之间发送,并且您可以配置许多复杂的设置来在Xeon系统上进行调整。(例如,请参阅有关Haswell Xeon的Anandtech文章。)