x86内存排序:加载与早期存储重新排序与处理器内转发



我正在努力理解《英特尔系统编程指南》第8.2节(PDF第3卷)。

特别是,我看到了两种不同的重新排序场景:

8.2.3.4装载物可能会与较早的仓库一起重新订购到不同的位置

8.2.3.5允许进行处理器内转发

然而,从战俘的可观察效果来看,我不理解这些场景之间的区别。这些章节中提供的例子对我来说似乎是可互换的。8.2.3.4例子可以用8.2.3.5规则来解释,也可以用它自己的规则来解释。相反的道理对我来说似乎也是正确的,尽管在这种情况下我不太确定。

因此,我的问题是:是否有更好的例子或解释8.2.3.4的可观察效果与8.2.3.5的可观察结果有何不同?

8.2.3.5中的示例应该是"令人惊讶的",如果您希望内存排序完全严格而干净,即使您承认8.2.3.4允许加载使用不同地址的存储进行重新排序。

Processor 0      |      Processor 1
--------------------------------------
mov [x],1        |      mov [y],1
mov R1, [x]      |      mov R3,[y]
mov R2, [y]      |      mov R4,[x]

请注意,关键部分是中间新添加的负载都返回1(存储到加载的转发使uarch中的这一点成为可能,而不会停滞)。因此,理论上,您可以预期,在完成这两个加载时,这两个存储都已被全局"观察"到(在顺序一致性的情况下,存储之间存在唯一的排序,所有核心都可以看到)。

然而,稍后的R2 = R4 = 0作为有效结果证明了情况并非如此——事实上,首先在本地观察存储。换句话说,允许这种结果意味着处理器0将存储视为time(x) < time(y),而处理器1则相反。

这是关于这个内存模型一致性的一个非常重要的观察结果,前面的例子没有证明这一点。这种细微差别是顺序一致性和总存储顺序之间的最大区别——第二个例子打破了SC,第一个没有。