является ли std :: atomic :: fetch_add операцией сериализации на x86-64? - PullRequest
0 голосов
/ 28 июня 2018

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

std::atomic<int> counter;

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

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

EDIT:

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

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Сначала давайте посмотрим, что разрешено делать компилятору при использовании 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 ЦП каждая операция RMW:

  • - это операция освобождения для операций с памятью, которые предшествуют ей, и операция получения для операций с памятью, которые следуют за ней.
  • становится видимым в едином общем порядке, наблюдаемом всеми потоками.
0 голосов
/ 28 июня 2018

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

С https://en.cppreference.com/w/cpp/atomic/memory_order:

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

...