c++, std::atomic, что такое порядок std:: memory и как их использовать?


может ли кто-нибудь объяснить, что такое std::memory_order на простом английском языке, и как их использовать с std::atomic?

Я нашел ссылку и несколько примеров здесь, но не понимаю вообще. http://en.cppreference.com/w/cpp/atomic/memory_order

спасибо.

5 57

5 ответов:

может ли кто-нибудь объяснить, что такое std::memory_order на простом английском языке,

лучшее" простое английское " объяснение, которое я нашел для различных упорядочений памяти, - это статья Бартоза Милевского о расслабленной атомике:http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/

и последующий пост:http://bartoszmilewski.com/2008/12/23/the-inscrutable-c-memory-model/

но обратите внимание, что в то время как эти статьи-хорошее введение, они предшествуют стандарту C++11 и не расскажут вам все, что вам нужно знать, чтобы использовать их безопасно.

и как их использовать с std:: atomic?

мой лучший совет вам здесь:не. Расслабленная атомика (вероятно) самая сложная и опасная вещь в C++11. Придерживайтесь std::atomic<T> с упорядочением памяти по умолчанию (последовательная согласованность), пока вы действительно не уверены, что у вас есть проблема производительности, которая может быть решена с помощью расслабленных упорядочений памяти.

во второй статье, приведенной выше, Бартоз Милевский приходит к следующему выводу:

Я понятия не имел, во что ввязываюсь, когда пытаюсь рассуждать о слабой атомной энергетике C++. Теория, стоящая за ними, настолько сложна, что это пограничный непригоден. Это заняло три человека (Энтони, Ганс и я) и модификация стандарта для завершения доказательства относительно простой алгоритм. Представьте, что вы делаете то же самое для очереди без блокировки на слабую атомику!

The std::memory_order значения позволяют указать мелкозернистые ограничения на порядок памяти, обеспечиваемый атомарными операциями. Если вы изменяете и получаете доступ к атомарным переменным из нескольких потоков, то передаете std::memory_order значения для ваших операций позволяют отдыхать ограничения на компилятор и процессор относительно порядка, в котором операции над этими атомарными переменными становятся видимыми для других потоков, и влияние синхронизации, которое эти операции оказывают на неатомные данные в вашем приложении.

порядок по умолчанию std::memory_order_seq_cst является наиболее ограниченным и обеспечивает "интуитивные" свойства, которые вы могли бы ожидать: если поток A хранит некоторые данные, а затем устанавливает атомарный флаг с помощью std::memory_order_seq_cst, затем, если поток B видит, что флаг установлен, то он может видеть, что данные, записанные потоком A. другие значения порядка памяти не обязательно обеспечивают эту гарантию и поэтому должны использоваться очень осторожно.

основная предпосылка такова: не используйте все, кроме std::memory_order_seq_cst (по умолчанию), если (А) вы реально действительно знайте, что вы делаете, и можете доказать что расслабленное использование безопасно во всех случаях, и (b) ваш профилировщик демонстрирует, что структура данных и операции, с которыми вы собираетесь использовать расслабленные заказы, являются узким местом.

моей книги параллелизм C++ в действии посвящает целую главу (45 страниц) деталям модели памяти C++, атомарным операциям а то std::memory_order ограничения, и еще одна глава (44 страницы) об использовании атомарных операций для синхронизации в незамкнутых структурах данных и последствиях ослабленных ограничений упорядочения.

мои записи в блоге на алгоритм Деккера и алгоритм Петерсона для взаимного исключения продемонстрируйте некоторые из вопросов.

нет. "Простое английское" объяснение занимает 32 страницы и может быть найдено здесь.

Если вы не хотите читать это, вы можете забыть о заказе памяти, потому что страница, на которую вы ссылаетесь, говорит, что по умолчанию последовательно-последовательный порядок, который "всегда делает разумную вещь"-настройка.

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

короче говоря, ваш компилятор и процессор могут выполнять инструкции в порядке, отличном от того, как вы их написали. Для одного потока это не проблема, как это будет выглядеть правильно. Для нескольких потоков на нескольких процессорах это становится проблемой. Упорядочение памяти в C++ ограничивает то, что может сделать ваш компилятор/процессор, и устраняет такие проблемы.

например, если вы посмотрите на мою статью о двойная проверка блокировки вы можете видеть, как заказ беспорядок с этим рисунком-это упоминание показать атомарный порядок памяти можно использовать для его исправления.

о самом переупорядочении вы также можете рассмотреть переопределение процессора -- опять же, компилятор также может выполнять переупорядочивание.

имейте в виду, что любые документы по этой теме (в том числе и мои) предлагают говорить о теоретических сценариях. Наиболее распространенные процессоры, такие как x86, имеют очень сильные гарантии упорядочения, так что много явного упорядочения просто не требуется. Таким образом, даже если вы не используете правильный C++11 атомика ваш код, скорее всего, все еще будет работать.

как упоминал зврба, тема на самом деле довольно подробная. Документ ядра linux на барьеры памяти также содержит много подробной информации.

в GCC wiki есть простой английский язык. ;)

http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync