C++中未定义对`__atomic_load_16`的引用

10

我在尝试进行16字节块的原子加载时出现了连接错误。我有以下代码:

#include <atomic>

struct MyStruct{
  long x; long y;
};

struct X{
  std::atomic<MyStruct> myStruct;
};

int main(){
  X x;
  MyStruct s = atomic_load(&x.myStruct);
}

当我使用(g++版本5.3.1)编译此代码时:
g++ --std=c++11 test.cpp

我遇到了错误

/tmp/ccrvzLMq.o: In function `std::atomic<MyStruct>::load(std::memory_order) const':
test.cpp:(.text._ZNKSt6atomicI8MyStructE4loadESt12memory_order[_ZNKSt6atomicI8MyStructE4loadESt12memory_order]+0x1c): undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status

如果(在另一篇文章中的提示后)我添加了“-latomic”标志,我会收到错误信息“/bin/ld:找不到/usr/lib64/libatomic.so.1.1.0”。实际上,该文件确实不存在。
有什么建议吗?
Gavin

1
使用您的软件包管理器安装原子库。 - uh oh somebody needs a pupper
6
尝试使用-march=native选项? - Kerrek SB
您的硬件不支持16位原子操作。 - Sam Varshavchik
1
@KerrekSB 那个方法有效,谢谢! - Gavin Lowe
2
@SamVarshavchik 他的硬件可能有,但GCC在向旧的X86/X64 CPU保持向后兼容性方面非常保守。编译器制造商不希望代码出现问题,因为你在新机器上编译,然后稍后在性能较差的机器上运行它。 - Kai Petzke
1个回答

2

对于Clang编译器也是同样的问题,简而言之:需要安装libatomic并链接它。(在RHEL中,该库名为libatomic.so.1,因此您可能需要使用-l:libatomic.so.1来设置名称)

https://releases.llvm.org/14.0.0/tools/clang/docs/Toolchain.html#libatomic-gnu

如果编译器不知道如何将你的 'c++_atomic_operation_code' 翻译成 CPU 指令,它会请求 libatomic 的帮助。默认的编译参数使程序在 x86/64 CPU 上更普遍地运行,因此一些 CPU 指令被禁用。
另一方面,使用 libatomic 有机会以更快的速度执行更现代的指令,请参见下面的注释。感谢 @Peter Cordes
-march=native 中,编译器可以利用更多的指令集来翻译代码。(你的 CPU 比 Generial-x86/64-CPU 更好)
或者链接到 libatomic 来避免分配 -march
例如,使用 tbb,通常会要求使用 libatomic 使算法更普遍。

1
GCC7及以上版本始终调用libatomic进行16字节的加载/存储,即使您使用-mcx16。这证明是一个明智的决定,因为libatomic可以在运行时选择在支持AVX的CPU上使用movaps,至少Intel最近已经记录了AVX特征位意味着16字节原子加载/存储保证。(SSE instructions: which CPUs can do atomic 16B memory operations?) - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接