c ++, std :: atomic, что такое std :: memory_order и как их использовать? - PullRequest
61 голосов
/ 04 марта 2012

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

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

Спасибо.

Ответы [ 5 ]

34 голосов
/ 05 марта 2012

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

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

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

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

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

22 голосов
/ 05 марта 2012

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

Лучшим объяснением "простого английского", которое я нашел для различных упорядочений памяти, является статья Бартоза Милевского о расслабленномatomics: 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 ++.Теория, стоящая за ними, настолько сложна, что ее невозможно использовать.Потребовалось три человека (Энтони, Ганс и я) и модификация Стандарта, чтобы завершить доказательство относительно простого алгоритма.Представьте, что вы делаете то же самое для очереди без блокировки, основанной на слабых атомах!

15 голосов
/ 04 марта 2012

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

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

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

5 голосов
/ 04 марта 2012

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

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

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

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

Как упоминалось в zvrba, тема на самом деле довольно детальная.Документация по ядру Linux на барьерах памяти также содержит много подробной информации.

4 голосов
/ 12 марта 2012

В вики GCC есть простой английский.;)

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

...