lock addl $0, (%esp)
является заменой mfence
, а не lfence
.
. Вариант использования - когда вам нужно заблокировать переупорядочение StoreLoad (единственный вид, который позволяет модель сильной памяти x86), новам не нужна атомарная операция RMW с общей переменной.https://preshing.com/20120515/memory-reordering-caught-in-the-act/
например, предполагая, что выровнено std::atomic<int> a,b
:
movl $1, a a = 1; Atomic for aligned a
# barrier needed here
movl b, %eax tmp = b; Atomic for aligned b
Возможны следующие варианты:
- Создать хранилище последовательной согласованности с
xchg
, например mov $1, %eax
/ xchg %eax, a
, поэтому вам не нужен отдельный барьер;это часть магазина.Я думаю, что это самый эффективный вариант на самом современном оборудовании;Компиляторы C ++ 11, кроме gcc, используют xchg
для хранилищ seq_cst. - Используйте
mfence
в качестве барьера.(gcc использует mov
+ mfence
для магазинов seq_cst). Используйте lock addl $0, (%esp)
в качестве барьера.Любая инструкция lock
является полным барьером. Имеет ли блокировка xchg такое же поведение, как и у mfence?
(Или в каком-то другом месте, но стек почти всегда приватный и горячий в L1d, так что это несколько хороший кандидат. Однако этоможет создать цепочку зависимостей для чего-либо, используя данные в нижней части стека.)
Вы можете использовать xchg
в качестве барьера, только сложив его в хранилище, потому что оно безоговорочно записываетячейка памяти со значением, которое не зависит от старого значения.
Когда это возможно, лучше использовать xchg
для хранилища seq-cst, даже если оно также считывает данные из общей папки.mfence
медленнее, чем ожидалось, на последних процессорах Intel ( Является ли загрузка и сохранение единственными командами, которые переупорядочиваются? ), также блокируя неупорядоченное выполнение независимых инструкций без памяти lfence
делает.
Возможно, даже стоит использовать lock addl $0, (%esp)/(%rsp)
вместо mfence
, даже когда mfence
доступно, но я не экспериментировал с недостатками.Использование -64(%rsp)
или чего-либо еще может снизить вероятность зависимости данных от чего-то горячего (локальный или обратный адрес), но это может сделать такие инструменты, как valgrind, несчастными.
lfence
никогда не используется для упорядочения памяти, если вы не читаете из видеопамяти RAM (или некоторой другой слабо упорядоченной области WC) с загрузками MOVNTDQA.
Сериализация неупорядоченного выполнения (но неБуфер хранилища) бесполезен для остановки переупорядочения StoreLoad (единственный тип, который модель сильной памяти x86 допускает для нормальных областей памяти WB (с обратной записью)).
Реальные сценарии использования для lfence
предназначены для блокирования выполнения не по порядку rdtsc
для синхронизации очень коротких блоков кода или для ослабления Спектра путем блокирования спекуляций через условную или косвенную ветвь.
См. также Когда следует использовать_mm_sfence _mm_lfence и _mm_mfence (мой ответ и ответ @ BeeOnRope), чтобы узнать больше о том, почему lfence
бесполезен, и когда использовать каждый из барьеров,ионов.(Или, по моему, встроенные функции C ++ при программировании на C ++ вместо asm).