ограждения / барьеры памяти в C ++: есть ли в boost или в других библиотеках они есть? - PullRequest
2 голосов
/ 04 октября 2010

В эти дни я читаю об ограждениях и барьерах памяти как о способе синхронизации многопоточного кода и предотвращения переупорядочения кода.

Я обычно разрабатываю на C ++ под ОС Linux и использую boost libs, но не могу найти ни одного класса, связанного с ним. Знаете ли вы, что барьер памяти ограждений присутствует в усилении или есть способ достичь той же концепции? Если нет, на какую хорошую библиотеку я могу взглянуть?

Ответы [ 3 ]

5 голосов
/ 04 октября 2010

В boost пока нет низкоуровневых барьеров памяти, но есть предлагаемая библиотека boost.atomic, которая их предоставляет.

Компиляторы предоставляют свои собственные функции как встроенные, так и библиотечные, например gcc's * 1003.* или _mm_mfence() для Visual Studio.

Библиотека C ++ 0x предоставляет элементарные операции, включая ограждения памяти, в виде std::atomic_thread_fence.Хотя gcc предоставляет различные формы атома C ++ 0x начиная с V4.4, ни V4.4, ни V4.5 не включают эту форму ограждения.Моя (коммерческая) библиотека just::thread обеспечивает полную реализацию атомарности C ++ 0x, включая заборы для g ++ 4.3 и 4.4 и Microsoft Visual Studio 2005, 2008 и 2010.

1 голос
/ 09 февраля 2012

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

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

Мне только что понадобились (умеренно) переносимые реализации барьера памяти (ARM и x86), а также я нашел, что дерево исходных текстов Linux является лучшим источником для этого. В Linux есть SMP-варианты макросов mb(), rmb() и wmb(), которые на некоторых платформах приводят к более конкретным (и, возможно, менее затратным) барьерам, чем не-SMP-варианты.
Это не является проблемой для x86 и, в частности, для ARM, где оба реализованы одинаково.

Это то, что я собрал вместе из заголовочных файлов linux (подходит для ARMv7 и не древних процессоров x86 / x64)

#if defined(__i386__ ) || defined(__x64__)

#define smp_mb()    asm volatile("mfence":::"memory")
#define smp_rmb()   asm volatile("lfence":::"memory")
#define smp_wmb()   asm volatile("sfence" ::: "memory")
#endif

#if defined(__arm__)

#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")

#define smp_mb()    dmb()
#define smp_rmb()   dmb()
#define smp_wmb()   dmb()
#endif

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

Кстати, в документации по ядру Linux .

очень хорошее описание барьеров памяти.
0 голосов
/ 04 октября 2010

Существует класс / концепция boost::barrier, но это немного высокий уровень. Кстати говоря, зачем вам барьер низкого уровня? Примитивов синхронизации должно быть достаточно, не так ли? И при необходимости они должны использовать барьеры памяти, прямо или косвенно, через другие примитивы более низкого уровня.

Если вы все еще думаете, что вам нужна низкоуровневая реализация, я не знаю ни классов, ни библиотек, которые реализуют барьеры, но в ядре Linux есть некоторый специфичный для реализации код. Искать mb(), rmb() или wmb() в include/asm-{arch}/system.h.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...