c - 乱序执行和内存栅栏

标签 c x86 cpu memory-barriers memory-fences

我知道现代 CPU 可以乱序执行,但是它们总是按顺序退出结果,如维基百科所述。

“Out of Oder 处理器及时用其他就绪的指令填充这些“插槽”,然后在末尾对结果重新排序,使指令看起来像是正常处理的。 "

现在据说在使用多核平台时需要内存栅栏,因为由于乱序执行,可以在此处打印错误的 x 值。

Processor #1:
 while f == 0
  ;
 print x; // x might not be 42 here

Processor #2:
 x = 42;
 // Memory fence required here
 f = 1

现在我的问题是,由于无序处理器(我假设是多核处理器的核心)总是按顺序退出结果,那么内存栅栏的必要性是什么。多核处理器的内核不会看到仅从其他内核退役的结果,或者它们也看到正在运行的结果吗?

我的意思是在我上面给出的例子中,当处理器 2 最终退出结果时,x 的结果应该在 f 之前,对吧?我知道在乱序执行期间它可能在 x 之前修改了 f 但它一定没有在 x 之前退出它,对吧?

现在有了按顺序退出结果和缓存一致性机制,为什么在 x86 中还需要内存栅栏?

最佳答案

本教程解释了这些问题:http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

FWIW,内存排序问题发生在现代 x86 处理器上,原因是虽然 x86 内存一致性模型提供了相当强的一致性,但需要明确的障碍来处理先写后读的一致性。这是由于称为“存储缓冲区”的东西。

也就是说,x86 是顺序一致的(良好且易于推理),除了加载可能会根据较早的存储重新排序。也就是说,如果处理器执行序列

store x
load y

然后在处理器总线上这可能被视为

load y
store x

此行为的原因是前面提到的存储缓冲区,它是在写入系统总线之前写入的一个小缓冲区。 OTOH,加载延迟是性能的关键问题,因此允许加载“插队”。

参见 http://download.intel.com/design/processor/manuals/253668.pdf 中的第 8.2 节

关于c - 乱序执行和内存栅栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7346893/

相关文章:

c - strncpy 添加字符

c - 列表中具有特定功能的最小元素

linux - 长时间监控linux进程,保存成文本文件或csv文件

python - 在 CPU 和 GPU 上的两个独立的 jupyter 笔记本中训练 Keras 模型

c - 在 for 循环中使用指针

c - 在 Visual Studio 中将 C 模块链接到 MASM

c++ - 如何隐藏SHLD延迟?

assembly - 引导加载程序在真实硬件上打印垃圾

c++ - 更短的循环,相同的覆盖范围,为什么我在使用 Visual Studio 2013 的 C++ 中得到更多的末级缓存未命中?

binary - 计算机如何将二进制数转换为 2 的补码形式的十进制数