Доступ к C++11 std atomic без каких-либо ограничений порядка памяти

Различные алгоритмы без блокировки не имеют требований к порядку загрузки или сохранения в быстром пути. Например, в этом краже работы 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 во время компиляции?

(Обратите внимание, что я не говорю о смешении атомарного и неатомарного доступа, так как меня интересуют целочисленные типы, нормальная загрузка и сохранение которых уже являются атомарными в архитектуре, на которую я ориентируюсь.)


person Display Name    schedule 27.03.2014    source источник
comment
по крайней мере, из того, что я вижу в реализации Visual C++ 2012 IIRC, эта реализация была неоптимальный. Связано: stackoverflow.com/q/13213113/420683   -  person dyp    schedule 28.03.2014
comment
dyp, спасибо за комментарий. _InterlockedOr для загрузки, безусловно, кажется недосмотром с их стороны, но с точки зрения правильной реализации, не будет ли переупорядочение компилятора по-прежнему заблокировано, что потенциально может предотвратить возможные оптимизации?   -  person Display Name    schedule 28.03.2014
comment
В VS2013 расслабленный std::atomic<int>::store на не-ARM (и в режиме отладки) — это просто *_Tgt = _Value; и ничего более. Эти барьеры компилятора не нужны, насколько мне известно. Расслабленное упорядочение памяти гарантирует только атомарный доступ к данным и не обеспечивает упорядочение между потоками.   -  person dyp    schedule 28.03.2014
comment
Этот документ очень интересен, но для ясности: он не устраняет все необходимые упорядочения памяти на быстром пути (также не утверждает этого), а только барьеры Store-Load. Теперь для x86 это единственный тип, который вам нужен, потому что остальные являются неявными и являются самым дорогим типом барьера для всех ISA, но имейте в виду, что на других ISA вы не можете использовать только обычную нагрузку! Не знаю, как это сделать для особого случая x86, хотя - кроме встроенной сборки (gcc позволяет синтаксису сделать это эффективным и позволить оптимизатору работать над ним, не думайте, что MSVC делает, и это не С++ 11 в любом случае)   -  person Voo    schedule 28.03.2014
comment
Спасибо. Я обновлюсь до VS2013, но пока, поскольку я не могу проверить источник, сохраняется ли сохранение/загрузка в volatile на не-ARM?   -  person Display Name    schedule 28.03.2014
comment
Да, он использует __iso_volatile_store32 для ARM.   -  person dyp    schedule 28.03.2014
comment
Извините, я имел в виду конкретно для x86.   -  person Display Name    schedule 29.03.2014