Различные алгоритмы без блокировки не имеют требований к порядку загрузки или сохранения в быстром пути. Например, в этом краже работы http://www.cs.rice.edu/~vs3/PDF/ppopp.09/p45-michael.pdf операция кражи требует атомарного сравнения и замены, но частые операции (положить и взять) специально разработаны чтобы не нуждаться в каких-либо ограничениях на порядок. Я сталкивался с таким паттерном во многих других случаях.
Так почему же нет способа получить доступ к стандартным атомарным переменным без ограничения памяти? В то время как на x-86(-64) memory_order_relaxed не вставляет никаких инструкций барьера ЦП, он предотвращает переупорядочивание компилятора (по крайней мере, из того, что я вижу в реализации Visual C++ 2012), что все еще, безусловно, имеет отрицательную производительность. Действительно, поскольку порядок памяти является параметром времени выполнения, также возникает штраф за ветвление. В совокупности это еще больше усугубляет ситуацию. Вот код в реализации Visual C++ 2012, который сохраняет значение uint32_t в atomic_uint32_t после того, как оператор switch определяет, что это memory_order_relaxed (см. xatomic.h):
_Compiler_barrier();
__asm
{
mov eax, _Value;
mov edx, _Tgt;
mov [edx], eax;
}
_Compiler_barrier();
Затем загрузка с memory_order_relaxed заканчивается выполнением
_Value = _InterlockedOr((volatile long *)_Tgt, 0);
что еще хуже, поскольку встроенная функция _InterlockedOr представляет собой полный барьер процессора (xatomic.h).
Итак, 1) почему упорядоченный доступ без памяти не является частью std API, и 2) что такое обходной путь, кроме свертывания собственного атомарного API, кроме уродливого reinterpret_cast атомарного класса к неатомарному типу и выполняете некоторую проверку sizeof и offsetof во время компиляции?
(Обратите внимание, что я не говорю о смешении атомарного и неатомарного доступа, так как меня интересуют целочисленные типы, нормальная загрузка и сохранение которых уже являются атомарными в архитектуре, на которую я ориентируюсь.)
std::atomic<int>::store
на не-ARM (и в режиме отладки) — это просто*_Tgt = _Value;
и ничего более. Эти барьеры компилятора не нужны, насколько мне известно. Расслабленное упорядочение памяти гарантирует только атомарный доступ к данным и не обеспечивает упорядочение между потоками. - person dyp   schedule 28.03.2014__iso_volatile_store32
для ARM. - person dyp   schedule 28.03.2014