X86 如何在微观架构上实现记忆屏障的传递性/累积性特性?

X86 如何在微观架构上实现记忆屏障的传递性/累积性特性?,x86,x86-64,cpu-architecture,memory-barriers,micro-architecture,X86,X86 64,Cpu Architecture,Memory Barriers,Micro Architecture,我一直在阅读x86内存模型的工作原理以及x86上的屏障指令的重要性,并与其他架构(如ARMv8)进行了比较。在x86和ARMv8体系结构中,内存模型似乎(并非有意双关语)尊重传递性/累积性,即如果CPU 1看到CPU0的存储,而CPU2看到CPU1的存储,这只有在CPU1看到CPU0存储时才会发生,那么CPU2也必须看到CPU0的存储。我所指的例子是保罗·麦肯尼的著名论文第6.1节中的例子1和2(虽然相关,但很老,在他最新的perf-cook书中也有同样的内容)。如果我理解正确,x86使用存储队

我一直在阅读x86内存模型的工作原理以及x86上的屏障指令的重要性,并与其他架构(如ARMv8)进行了比较。在x86和ARMv8体系结构中,内存模型似乎(并非有意双关语)尊重传递性/累积性,即如果CPU 1看到CPU0的存储,而CPU2看到CPU1的存储,这只有在CPU1看到CPU0存储时才会发生,那么CPU2也必须看到CPU0的存储。我所指的例子是保罗·麦肯尼的著名论文第6.1节中的例子1和2(虽然相关,但很老,在他最新的perf-cook书中也有同样的内容)。如果我理解正确,x86使用存储队列(或存储顺序缓冲区)在存储全局可见(即写入L1D)之前对其进行排序(以及其他micro-arch优化)。我的问题是x86 arch(和其他arch)如何实现(微体系结构)传递性属性?存储队列确保特定CPU的存储以特定顺序全局可见,但如何确保一个CPU的存储顺序与不同CPU的存储顺序一致?在x86上,只有一个一致性域。当存储提交到L1d缓存时,所有其他核心将在同一时间看到它们。总的来说,加上MESI,就足以给我们一个所有线程都能同意的总存储订单

一些ISA(包括PowerPC)没有该属性(实际上是因为物理核心内的失效存储跨SMT线程进行存储转发)。因此,在POWER硬件上,其他两个阅读器可以以不同的顺序查看来自两个线程的
mou
存储。 (大概是PowerPC上的屏障阻止了该转发。)

ARM内存模型过去允许IRIW(独立读写器)重新排序,但实际上没有一个ARM硬件能够做到这一点。ARM能够增强他们的内存模型,以保证所有内核都同意由多个其他内核完成的存储的全局订单

(存储转发仍然意味着执行存储的核心在其变得全局可见之前就可以立即看到它。当然,负载排序要求核心能够说他们看到了他们观察到的关于独立写入排序的任何内容。)


如果所有Core都必须就存储的全局排序达成一致,那么(在您的示例中)从Core2看到存储意味着Core1一定已经发生了,并且您也可以看到它。

(假设Core2使用适当的屏障或获取加载或释放存储,以确保其存储发生在其加载看到Core1存储之后。)


可能还与:


最近,ARM决定指定他们的模型为多拷贝原子,因此我认为IRW在那里不再可能。我认为这确实回答了我的问题。为了澄清这一点,可传递性和TSO(至少在x86上)是使用MESI有效实现的,因为提交到L1D的任何写操作都将RFO缓存线,从而有效地使它的所有其他副本失效/删除。因此,如果任何CPU(提交CPU除外)能够读取特定位置,则所有CPU都能够读取该位置,即在这种情况下,不同CPU之间GV存储的传播没有延迟。我的理解正确吗?@BeeOnRope,正确。ARM确实转向了其他多拷贝原子性(基于您在不同答案中链接的论文)。大多数ARM系统使用MESI/MOESI/AMBA类型的协议,这些协议为存储请求缓存线。根据此问题和所有相关问题的答案,使用此类协议通常可以消除不同CPU以不同顺序看到存储的可能性,即保证存储的可传递性(忽略逻辑核之间SLF的power PC情况)。这是一个公平的说法吗?@Raghu:所有主流ISA都使用MESI(或其变体),创建一个单一的一致性域。是的,这就是为什么commit to L1d使存储对所有其他内核同时全局可见的原因。其他内核读取该行的唯一机制是发送请求以共享修改后的行。(除了PowerPC在SMT线程之间的存储转发)。x86通过将存储提交的顺序限制为每个核心内的程序顺序来获得TSO。(TSO是一个强有力的术语,而不仅仅是所有存储的全局订单的存在)。@Raghu:是的,弱有序的ISA-like ARM可以在提交之前将非相邻的存储合并,而x86只能将背靠背的存储合并到同一行。如果最早的条目的行还没有处于E或M状态,ARM可以扫描存储缓冲区以查找可能无序提交的条目。IDK实现这一点有多实际:在每个时钟周期检查缓存状态标记中的N个缓冲区条目似乎不切实际,但它可能会注意到RFO响应何时到达(行进入E状态)。