c - 内存栅栏如何工作?

标签 c assembly multicore parallel-processing microprocessors

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

核心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++ 代码中放置内存栅栏吗?

最佳答案

栅栏序列化它们栅栏的操作(加载和存储),也就是说,在执行栅栏之前不会开始其他操作,但在所有前面的操作完成之前栅栏不会执行。引用 intel 使它的含义更精确(取自 MFENCE 指令,第 3-628 页,第 2A 卷,Intel 指令引用):

This serializing operation guarantees that every load and store instruction that precedes the MFENCE instruction in program order becomes globally visible before any load or store instruction that follows the MFENCE instruction.1

  1. A load instruction is considered to become globally visible when the value to be loaded into its destination register is determined.

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

注意:这假定了英特尔的观点,即:使用 x86(32 或 64 位)或 IA64 处理器的观点

关于c - 内存栅栏如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7280119/

相关文章:

c - 如何从 C 程序输出主机的 IP 地址?

c - 为什么这个程序会截断数字?

c++ - 增加内存映射文件的大小

c++ - 有人可以解释 malloc(20 * c | -(20 * (unsigned __int64)(unsigned int)c >> 32 != 0)) 的含义

assembly - GCC 和 STM32 的堆栈帧不正确

c - C练习查询

assembly - 如何将 Intel 80386 机器代码转换为汇编语言?

python - 将 GILed Python 程序限制在单个 CPU 上会提高性能吗?

c++ - 使用多核提升协程

java - java程序在多核机器上如何提高性能