c++, std::atomic, что такое порядок std:: memory и как их использовать?
может ли кто-нибудь объяснить, что такое std::memory_order на простом английском языке, и как их использовать с std::atomic?
Я нашел ссылку и несколько примеров здесь, но не понимаю вообще. http://en.cppreference.com/w/cpp/atomic/memory_order
спасибо.
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 на барьеры памяти также содержит много подробной информации.