C++ 标准::原子<;布尔>;手臂无锁不一致(覆盆子皮3)

C++ 标准::原子<;布尔>;手臂无锁不一致(覆盆子皮3),c++,gcc,raspberry-pi,arm,stdatomic,C++,Gcc,Raspberry Pi,Arm,Stdatomic,我对静态断言有问题。静态断言与此完全相同: static_assert(std::atomic<bool>::is_always_lock_free); 正如你所看到的,它不像CPPPreference网站上所说的那样一致。。。为了比较,我在我的笔记本电脑(Ubuntu 18.04.5)上用g++7.5.0运行了它,得到了: ATOMIC_BOOL_LOCK_FREE --> 2 dummy.is_lock_free() --> true std::atomic_is_

我对静态断言有问题。静态断言与此完全相同:

static_assert(std::atomic<bool>::is_always_lock_free);
正如你所看到的,它不像CPPPreference网站上所说的那样一致。。。为了比较,我在我的笔记本电脑(Ubuntu 18.04.5)上用g++7.5.0运行了它,得到了:

ATOMIC_BOOL_LOCK_FREE --> 2
dummy.is_lock_free() --> true
std::atomic_is_lock_free(&dummy) --> true
std::atomic<bool>::is_always_lock_free --> true
ATOMIC\u BOOL\u LOCK\u FREE
(或
\u GCC\u ATOMIC\u BOOL\u LOCK\u FREE
)等于1或2有什么区别?在这种情况下,如果1,则它可能是无锁的,如果2,则它是100%无锁的?除了0,还有其他值吗?这是CPPPreference站点上的错误吗?该站点声明所有这些返回值应一致?raspberry pi输出的哪个结果是真的?

宏的意思是:

  • 0​,用于从不免锁的内置原子类型
  • 1
    用于有时无锁的内置原子类型
  • 2
    用于始终无锁的内置原子类型
因此,在您的PI环境中,
std::atomic
有时是无锁的,您正在测试的
dummy
实例是无锁的,这意味着所有实例都是无锁的

bool std::atomic\u是无锁的(const std::atomic*obj)

在任何给定的程序执行中,对于相同类型的所有指针,无锁查询的结果都是相同的

唯一的缺点是,在运行程序之前,您不知道该类型是否无锁

If(not std::atomic_is_lock_free(&dummy)) {
    std::cout << "Sorry, the program will be slower than expected\n";
}
If(非std::atomic_是无锁的(&dummy)){
std::cout
1
在标准中表示“有时无锁”。但实际上这表示“不知道在编译时是否无锁”。

在没有编译器选项的情况下,GCC的默认基线包括ARM芯片,它们太旧了,不支持原子RMW所需的指令,因此它必须生成可以在古老的CPU上运行的代码,总是调用libatomic函数,而不是内联原子操作

运行时查询函数在带有ARMv7或ARMv8 CPU的RPi上运行时返回true

-march=native
-mcpu=cortex-a53
的情况下,您会发现
始终是无锁的,因为编译时知道目标机器肯定支持所需的指令。(这些选项告诉GCC生成一个二进制文件,该二进制文件可能不会在其他/旧CPU上运行。)这是正确的

如果没有编译选项,
std::atomic
操作必须调用libatomic函数,因此即使在现代CPU上也会有额外的开销

GCC(和所有sane编译器)实现
std::atomic
的方式是,它对所有实例都是无锁的,或者没有锁,在运行时不检查每个对象的对齐方式或任何东西


alignof(std::atomic)
为8,即使在32位机器上
alignof(int64_t)
仅为4,因此如果原子对象未对齐,这是未定义的行为。(该UB的实际症状可能包括撕裂,即纯加载和纯存储的非原子性。)如果你遵循C++规则,你所有的原子对象都会被对齐;如果你把一个错误的指针抛到<代码>原子*<代码>,并试图使用它,你就只有一个问题。

最有可能的是,“有时无锁”意味着“编译时不知道是无锁的”。,但运行时查询函数在使用ARMv7 CPU的RPi上运行后返回true。可能是使用
-march=native
-mcpu=cortex时,无论您得到什么,都是\u始终\u锁定\u自由
true
。(如果没有编译选项,std::atomic操作必须调用
libatomic
函数,因此即使在现代CPU上也会有额外的开销)实现
std::atomic
,它对所有实例都是免锁的,或者没有,不检查每个实例在运行时的对齐方式或任何东西。彼得科德斯:这似乎是合理的。@Rogus你能试试
-m
选项看看它是否总是免锁的吗?我在编译中添加了
-mcpu=cortex-a53
,它成功了!
ATOMIC_BOOL_LOCK_FREE
为2且
std::atomic::is_always_LOCK_FREE
计算结果为
true
!非常感谢您的帮助!
ATOMIC_BOOL_LOCK_FREE --> 2
dummy.is_lock_free() --> true
std::atomic_is_lock_free(&dummy) --> true
std::atomic<bool>::is_always_lock_free --> true
c++/8/bits/atomic_lockfree_defines.h: #define ATOMIC_BOOL_LOCK_FREE  __GCC_ATOMIC_BOOL_LOCK_FREE
c++/8/atomic: static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2;
If(not std::atomic_is_lock_free(&dummy)) {
    std::cout << "Sorry, the program will be slower than expected\n";
}