【问题标题】:what happened if store with memory_order_acquire [closed]如果使用 memory_order_acquire 存储会发生什么 [关闭]
【发布时间】:2020-09-07 20:30:41
【问题描述】:

据我们所知: 加载 memory_order_acquire, 使用 memory_order_release 存储 然而, 我发现使用 gcc4.8.2,打开 -O2,抛出编译错误, /usr/include/c++/4.8.2/atomic:199:9: 错误:'__atomic_store' 的内存模型无效 但是如果关闭-O2,错误就消失了

此外,如果使用 gcc8.3.0,即使使用 -O2 也会引发错误

那么发生了什么?这要怎么解释?

【问题讨论】:

  • 你能给出一个失败的代码的具体例子吗? “open -O2”是指有这个选项,还是没有这个选项? “打开/关闭”不是命令行选项的标准术语。
  • 来自std::atomic<T>::store - 订单必须是memory_order_relaxedmemory_order_releasememory_order_seq_cst 之一。否则行为未定义。 如果寻找具体的 lib 实现(我寻找 msvc 而不是 gcc) - _Check_store_memory_orderstore - 可见 _INVALID_MEMORY_ORDER 案例已执行。扩展为空或_STL_REPORT_ERROR("Invalid memory order")
  • @Nate Eldredge open -O2 我的意思是这个选项

标签: c++ gcc memory-barriers stdatomic


【解决方案1】:

如果不进行优化,order 不会作为编译时常量对内置编译器可见,并且 GCC 只会将运行时变量顺序视为 seq_cst(而不是分支在值上跳过mfence)。需要对常量传播进行优化,以使非法的order 对检查它的编译器逻辑可见,并为您提供预期的错误。

std::atomic&lt;T&gt;::store() 是一个用 C++ 编写的函数,它接受 order 参数并将该变量传递给 GNU C 内置函数 __atomic_store

没有优化,就不会发生持续传播。 Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?。即使__attribute__((always_inline)) 在内联时也不会使编译器优化,它只是避免了实际的函数调用。 Why is this C++ wrapper class not being inlined away?

如果您查看生成的未优化 asm,甚至还有对 std::operator&amp;(std::memory_order, std::__memory_order_modifier) https://godbolt.org/z/dhViAG 的非内联调用。但是原子存储本身是内联的。

【讨论】:

  • 非常感谢,但我无法理解“而不是在值上分支以跳过 mfence”,为什么 gcc 只是将运行时变量订单视为 seq_cst?
  • @Chanjun:因为seq_cst总是足够强大,而运行时变量order基本上从不在源代码中使用。所以这只发生在未优化的代码上,这是一种减少臃肿 asm 的简单方法。不值得让编译器变得更复杂来做任何其他事情,因为它只会影响未优化的代码,而未优化的代码无关紧要。不要再浪费时间看它了,除非你想了解 GCC 的内部结构。
  • 生成的 GCC 未优化代码通常很丑陋,但使用 std::atomic,哎呀。真的很丑。
  • @curiousguy:模板化的 C++ 代码通常是没有优化的噩梦。 C11 stdatomic 是 IIRC,并不比你大多数时候预期的差多少。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
相关资源
最近更新 更多