Почему std::atomic<double> не реализован при компиляции с помощью clang?

Рассмотрим следующий фрагмент кода:

#include <atomic>

int main(void) {
  std::atomic<double> aDouble;
  aDouble = 6.0;
}

G ++ компилирует это просто отлично, в то время как clang++ производит следующее:

clang++ -std=c++11 Main.cpp 
/tmp/Main-d4f0fc.o: In function `std::atomic<double>::store(double, std::memory_order)':
Main.cpp:(.text._ZNSt6atomicIdE5storeEdSt12memory_order[_ZNSt6atomicIdE5storeEdSt12memory_order]+0x31): undefined reference to `__atomic_store_8'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Разве они не ссылаются на одну и ту же стандартную библиотеку?

1 ответ

Если clang++ -stdlib=libstdc++ не решает вашу проблему, свяжитесь с -latomic для реализации этих функций.

Попытайтесь заставить свой компилятор встроить 8-байтовые и более узкие атомы, потому что функции библиотеки имеют потенциально большие недостатки.

Помните, что библиотечные функции не поддерживают более слабый порядок памяти memory_order_seq_cstпоэтому они всегда используют mfence на x86, даже если источник использовал relaxed,


32-разрядная версия x86 __atomic_store_8 еще хуже: он использует lock cmpxchg8b вместо SSE или x87 8-байтовое хранилище. Это заставляет его работать, даже если он не выровнен, но при значительном снижении производительности. Он также имеет два избыточных lock or [esp], 0 инструкции как дополнительные барьеры для загрузки своих аргументов из стека. (Я смотрю на /usr/lib32/libatomic.so.1.2.0 из gcc7.1.1 в Arch Linux.)

По иронии судьбы, текущий gcc -m32 (в режиме C11, а не C++11) занижен atomic_llong внутри структуры, но внутри строк movq xmm загружает / хранит, так что это на самом деле не атомарно. ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65146)

Текущий лязг -m32 выравнивает atomic_llong до 8 байт даже внутри структур (в отличие от обычных long long, который i386 System V ABI выравнивает только до 4B). Ирония в том, что clang генерирует вызовы библиотечных функций, которые используют lock cmpxchg8b ( https://bugs.llvm.org/show_bug.cgi?id=33109), поэтому он на самом деле атомарен даже при разделении строк кэша. ( Почему целочисленное присваивание для естественно выровненной переменной атомарно в x86?).

Таким образом, clang безопасен, даже если какой-то gcc-скомпилированный код передает ему указатель на выровненный _Atomic long long, Но он не согласен с gcc по поводу разметки структуры, так что это может помочь, только если он получает указатель на атомарную переменную напрямую, а не на содержащую структуру.


Связанный: атомная двойная с плавающей точкой или SSE/AVX векторная загрузка / сохранение на x86_64

Другие вопросы по тегам