【发布时间】:2021-11-05 18:08:30
【问题描述】:
我一直在研究内存模型,看到了这个(引自https://research.swtch.com/hwmm):
Litmus Test: Write Queue (also called Store Buffer)
Can this program see r1 = 0, r2 = 0?
// Thread 1 // Thread 2
x = 1 y = 1
r1 = y r2 = x
On sequentially consistent hardware: no.
On x86 (or other TSO): yes!
-
事实 1:这是许多文章中提到的存储缓冲区试金石。他们都说 r1 和 r2 都为零可能发生在 TSO 上,因为存在存储缓冲区。他们似乎假设所有的存储和加载都是按顺序执行的,但结果是 r1 和 r2 都为零。这后来得出结论,“可能发生存储/加载重新排序”,作为“存储缓冲区存在的后果”。
-
事实 2:但是我们知道 OoO 执行也可以重新排序两个线程中的存储和加载。从这个意义上说,无论存储缓冲区如何,只要所有四个指令都退出而没有看到彼此对 x 或 y 的无效,这种重新排序可能导致 r1 和 r2 都为零。在我看来,“可能会发生存储/加载重新排序”,只是因为“它们是无序执行的”。 (我可能对此非常错误,因为这是我所知道的关于推测和 OoO 执行的最好的。)
我想知道这两个事实如何融合(假设我碰巧对两者都是正确的):存储缓冲区或 OoO 执行是“存储/加载重新排序”的原因,还是两者都是?
换一种说法:假设我以某种方式在 x86 机器上观察到这个试金石测试,是因为存储缓冲区还是 OoO 执行?或者甚至有可能知道哪个?
编辑:实际上我的主要困惑是各种文献中以下几点之间的因果关系不明确:
- OoO 执行会导致内存重新排序;
- 存储/加载重新排序是由存储缓冲区引起的,并由石蕊测试证明(因此称为“存储缓冲区”);
- 使用与存储缓冲区石蕊测试具有完全相同指令的某些程序作为可观察的 OoO 执行示例,正如本文https://preshing.com/20120515/memory-reordering-caught-in-the-act 所做的那样。
1 + 2 似乎暗示存储缓冲区是原因,而 OoO 执行是结果。 3 + 1 似乎暗示 OoO 执行是原因,内存重新排序是结果。我再也说不出是哪个原因了。正是这个谜团中的试金石。
【问题讨论】:
-
标题问题的目的是为了说明为什么这样称呼它,对吧?不是为什么使用该代码的 StoreLoad 重新排序试金石测试很有用。 (它很少相关;通常 acq/rel 同步对于线程间通信就足够了,但作为指定允许哪些重新排序效果的一种方式,它是必不可少的。preshing.com/20120515/memory-reordering-caught-in-the-act 是这个 x86 试金石测试的实际实现)。我编辑了您的标题以澄清这一点,因为这是我正在写的答案的方向。
-
重新整理思路后,我在问题正文中进行了一些编辑。但是,是的,您对图块的编辑仍然是我正在寻找的方向,加上您在下面的广泛回答解决了我所有的困惑。所以编辑肯定是 LGTM。
-
你写的 Preshing 的测试是用来检测“OoO 执行”的。他说的不完全是这样。 “因此,它可能会像指令按以下顺序执行一样结束:”。他确实使用了“执行”这个词,但我认为他的真正意思是,就好像程序顺序相反。或者就像在串行机器上以其他顺序执行一样。他不是试图暗示“OoO exec”是创建重新排序的特定机制。
-
请参阅preshing.com/20120710/…,他解释了“管道”如何延迟存储,以及(在底部)真正的 CPU 具有存储缓冲区,因此类比仅限于此。
-
cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf 这是和你一样的一群人写的,它在介绍中列出。 www0.cs.ucl.ac.uk/staff/j.alglave/papers/tacas11.pdf 这个也是由不同的人设计的。
标签: x86 cpu-architecture memory-barriers memory-model