【问题标题】:why C/C++ compiler not always make ++a atomic?为什么 C/C++ 编译器并不总是使 ++a 成为原子的?
【发布时间】:2018-01-14 07:10:52
【问题描述】:

正如标题,当我们在C/C++中写++a时,编译器似乎可以编译为:

inc dword ptr[i]

这是原子的, 或:

mov eax,  dword ptr[i]
inc eax
mov dword ptr[i], eax

这不是原子的。

将其编译为非原子样式有什么好处吗?

【问题讨论】:

  • inc dword ptr[i] 首先是不是原子的。只有使用lock 前缀,它才会变成原子的——它也会变得超级慢。
  • 请注意,许多 CPU 没有 inc dword ptr[i] 的等价物。大多数“RISC”机器只有两种访问内存的指令:加载和存储。所有算术指令都只对寄存器中的值进行操作。
  • 如果显示程序集,请考虑添加特定于平台的标签
  • 不,可能不是。可能会稍微提高解码速度,但这很可能是全部。
  • x86/x64 CPU 无法按您预期的方式工作。您编写或编译器生成的指令并不是 CPU 内部执行的实际指令。它们被转换为在 CPU 的各种执行单元中调度的微操作。这些微操作可能会乱序执行,也可能会被推测执行(当有分支时,CPU 可能会执行两条条指令路径,然后丢弃原来未被采用的一条) .在 x86/64 机器代码中看不到许多正在发生的事情。 (任何人都可以推荐一个很好的介绍吗?)

标签: c++ c compiler-construction atomic


【解决方案1】:

如果你的代码是这样的呢?

++a;
if (a > 1) {
  ...
}

如果编译器使用第一种表示,它访问内存以递增a,然后再次访问内存以与1 进行比较。在第二种情况下,它访问内存以获取一次值并将其放入eax。然后它只是将寄存器eax1 进行比较,这明显更快。

【讨论】:

    【解决方案2】:

    首先,您似乎想到了一个非常特殊的处理器系列。并非所有指令都直接作用于内存。

    即使他们有,这种单一的指令也可能是一件非常复杂和昂贵的事情。如果它真的像您声称的那样是原子的,它必须停止所有其他总线传输。这将计算速度减慢到内存总线的速度。这通常是比 CPU 慢的命令。

    【讨论】:

      【解决方案3】:

      非原子变体结束了寄存器中的值以供以后使用。

      【讨论】:

        猜你喜欢
        • 2014-06-17
        • 1970-01-01
        • 2015-01-30
        • 2010-12-18
        • 2011-12-13
        • 1970-01-01
        • 1970-01-01
        • 2015-01-17
        • 1970-01-01
        相关资源
        最近更新 更多