【问题标题】:Are unnecessary atomics eliminated by the compiler?编译器是否消除了不必要的原子?
【发布时间】:2018-11-26 00:15:06
【问题描述】:

如果我声明一个仅在单个线程中使用的原子变量,编译器是否能够对其进行优化,并在某些情况下将 std::atomic<T> 替换为 T

我读过一些关于 atimics 的编译器优化的文章,但它们大多是关于对锁和存储进行重新排序和分组,而不是关于消除它们。

我们以std:shared_pointer 为例。它有一个原子计数器,但如果只有一个线程可以访问它,它可以被一个简单的计数器替换,它仍然会表现得好像它是一个原子的。

【问题讨论】:

  • 取决于情况和编译器的糟糕程度。但通常,由于“原子”在许多情况下意味着“易变”,所以不是。
  • 在这种情况下,有时:godbolt.org/g/64o5v3 - 我还没有找到 有趣的 案例(肯定没有 shared_ptr 这么复杂)
  • @david: atomic 和 volotile 之间没有联系,除了过去的误用
  • @JVApen 原子访问中的无链接不是易失性访问,但在实践中存在很多重叠。值得注意的是,消费语义是可变语义(几乎)。

标签: c++ multithreading c++11 atomic compiler-optimization


【解决方案1】:

答案取决于您假设优化原子的内容。使用原子有两个效果:强制执行语句的可观察顺序并确保处理器缓存失效。

如果您使用的是 Intel 处理器,则可以简单地删除后者的大部分。这是因为处理器保证了相同的行为,不需要进行特定的处理。

但是对于订购,情况就不同了。为了消除排序约束,您的编译器应该能够证明您没有不同的可观察行为。

实际上,如果您将指针或引用传递给不同编译单元中的函数,编译器将无法进行优化。另一方面,如果编译器对使用情况有充分的了解,它可以断定不需要内存屏障,并在此基础上消除它们。

解决代码生成问题是很容易解决的问题,据我所知,大多数行业编译器至少对此有一些支持。 消除另一端的内存障碍是外向研究的一部分,因此您可能无法使用此方法,或者可能仅涵盖非常简单的情况。

当您询问此问题时,认为您更了解您的用例可能听起来很合理。但是,我建议您在需要原子行为时保留原子。手动优化非常耗时,而好处可能并不明显。

【讨论】:

    猜你喜欢
    • 2019-06-27
    • 1970-01-01
    • 2018-05-26
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多