такое std :: atomic :: fetch_add — это операция сериализации на x86-64?

Учитывая следующий код:

std::atomic<int> counter;

/* otherStuff 1 */
counter.fetch_add(1, std::memory_order_relaxed);
/* otherStuff 2 */

Есть ли в x86-64 инструкция (скажем, менее 5-летней архитектуры), которая позволила бы переупорядочить otherStuff 1 и 2 через fetch_add или это будет всегда сериализация?

РЕДАКТИРОВАТЬ:

Похоже, это суммируется lock add барьер памяти на x86? »и, похоже, это не так, хотя я не уверен, где найти ссылку на это.

3

Решение

Сначала давайте посмотрим, что разрешено делать компилятору при использовании std::memory_order_relaxed,
Если нет зависимости между otherStuff 1/2 и атомная операция, это, конечно, может изменить порядок заявлений. Например:

g = 3;
a.fetch_add(1, memory_order_relaxed);
g += 12;

clang ++ генерирует следующую сборку:

lock   addl $0x1,0x2009f5(%rip)        # 0x601040 <a>
movl   $0xf,0x2009e7(%rip)             # 0x60103c <g>

Здесь Clang позволил себе изменить порядок g = 3 с атомным fetch_add операция, которая является законным преобразованием.

Когда используешь std::memory_order_seq_cst, вывод компилятора становится:

movl   $0x3,0x2009f2(%rip)        # 0x60103c <g>
lock   addl $0x1,0x2009eb(%rip)   # 0x601040 <a>
addl   $0xc,0x2009e0(%rip)        # 0x60103c <g>

Переупорядочение операторов не происходит, потому что компилятору не разрешено это делать.
Последовательное последовательное упорядочение в операции чтения-изменения-записи (RMW) является одновременно выпуском и операцией получения, и, как таковое, не допускается (видимое) переупорядочение операторов как на уровне компилятора, так и на уровне ЦП.

Ваш вопрос: X86-64, std::atomic::fetch_addс использованием упорядоченного упорядочения является операцией сериализации.
Ответ: да, если вы не учитываете переупорядочение компилятора.

На X86 В архитектуре операция RMW всегда очищает буфер хранилища и поэтому является последовательной и последовательной последовательной операцией.

Вы можете сказать, что на X86 CPU, каждая операция RMW:

  • является операцией освобождения для операций с памятью, которые предшествуют ей, и является операцией получения для операций с памятью, которые следуют за ней.
  • становится видимым в едином общем порядке, наблюдаемом всеми потоками.
4

Другие решения

Когда используешь std::memory_order_relaxed единственная гарантия состоит в том, что операция является атомной. Все что угодно вокруг операции может быть переупорядочено по желанию либо компилятором, либо процессором.

От https://en.cppreference.com/w/cpp/atomic/memory_order:

Расслабленная работа: нет синхронизации или заказа
ограничения, накладываемые на другие операции чтения или записи, только эта операция
атомарность гарантируется (см. «Расслабленный порядок» ниже)

-1

По вопросам рекламы [email protected]