25

我需要了解多核机器中的内存栅栏。说我有这个代码

核心1

mov [_x], 1; mov r1, [_y]    

核心 2

mov [_y], 1; mov r2, [_x]

现在没有内存栅栏的意外结果将是执行后 r1 和 r2 都可以为 0。在我看来,为了解决这个问题,我们应该在两个代码中都放置内存栅栏,因为只放置一个仍然不能解决问题。如下所示...

核心1

mov [_x], 1; memory_fence; mov r1, [_y]  

核心 2

mov [_y], 1; memory_fence; mov r2, [_x]

我的理解正确还是我仍然遗漏了什么?假设架构是 x86。另外,有人能告诉我如何在 C++ 代码中放置内存栅栏吗?

4

2 回答 2

15

栅栏将它们栅栏的操作(加载和存储)序列化,也就是说,在栅栏执行之前不能开始其他操作,但栅栏要等到所有前面的操作都完成后才会执行。引用 intel 使这个含义更加精确(取自 MFENCE 指令,第 3-628 页,第 2A 卷,英特尔指令参考):

此序列化操作可确保在程序顺序中位于 MFENCE 指令之前的每个加载和存储指令在 MFENCE 指令之后的任何加载或存储指令之前都变得全局可见。 1

  1. 当确定要加载到其目标寄存器的值时,加载指令被认为是全局可见的。

在 C++ 中使用栅栏很棘手(C++11 可能在某处有栅栏语义,也许其他人有这方面的信息),因为它依赖于平台和编译器。对于使用 MSVC 或 ICC 的 x86,您可以使用_mm_lfence, _mm_sfence&_mm_mfence进行加载、存储和加载 + 存储防护(注意其中一些是 SSE2 指令)。

注意:这是假设 Intel 的观点,即:使用 x86(32 或 64 位)或 IA64 处理器

于 2011-09-02T07:22:39.447 回答
4

C++11 ( ISO/IEC 14882:2011 ) 定义了一个多线程感知内存模型。虽然我不知道目前有任何编译器实现了新的内存模型,但Anthony Williams 的 C++ Concurrency in Action很好地记录了它。你可以查看第 5 章 - The C++ Memory Model and Operations on Atomic Types,他解释了宽松的操作和内存栅栏。此外,他还是 just::thread 库的作者,该库在我们获得编译器供应商对新标准的支持之前可以使用。just::thread 是 boost::thread 库的基础。

于 2011-10-18T03:26:29.117 回答