В чем разница между атомным и критическим в OpenMP?

В чем разница между атомарным и критическим в OpenMP?

Я могу сделать это

 #pragma omp atomic
g_qCount++;

но это не то же самое, что

 #pragma omp critical
g_qCount++;

?

95 голосов | спросил codereviewanskquestions 17 +04002011-10-17T22:35:50+04:00312011bEurope/MoscowMon, 17 Oct 2011 22:35:50 +0400 2011, 22:35:50

8 ответов


0

Эффект на g_qCount тот же, но то, что сделано, отличается.

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

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

У атомарной операции намного меньше накладных расходов. Там, где это возможно, он использует преимущества аппаратного обеспечения, скажем, операции атомарного приращения; в этом случае нет необходимости в блокировке /разблокировке при входе /выходе из строки кода, он просто делает атомарный прирост, который, как сообщают аппаратные средства, не может вмешиваться.

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

Конечно, в любом случае вы платите за сериализацию.

ответил Jonathan Dursi 18 +04002011-10-18T00:11:40+04:00312011bEurope/MoscowTue, 18 Oct 2011 00:11:40 +0400 2011, 00:11:40
0

В OpenMP все безымянные критические разделы являются взаимоисключающими.

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

ответил Michael 27 FebruaryEurope/MoscowbMon, 27 Feb 2012 18:40:20 +0400000000pmMon, 27 Feb 2012 18:40:20 +040012 2012, 18:40:20
0

Критический раздел:

  • Обеспечивает сериализацию блоков кода.
  • Может быть расширен для сериализации групп блоков с правильным использованием тега "name".

  • Медленнее!

Атомная операция:

  • Это намного быстрее!

  • обеспечивает только сериализацию определенной операции.

ответил efarsarakis 23 MonEurope/Moscow2013-12-23T06:41:51+04:00Europe/Moscow12bEurope/MoscowMon, 23 Dec 2013 06:41:51 +0400 2013, 06:41:51
0

Самый быстрый способ не является ни критическим, ни атомарным. Примерно, сложение с критическим сечением в 200 раз дороже простого сложения, атомарное сложение в 25 раз дороже простого сложения.

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

ответил Andrii 26 Jpm1000000pmSun, 26 Jan 2014 18:39:29 +040014 2014, 18:39:29
0

Ограничения atomic важны. Они должны быть подробно описаны в спецификациях OpenMP . MSDN предлагает быстрый шпаргалку, так как Я не удивлюсь, если это не изменится. (Visual Studio 2012 имеет реализацию OpenMP с марта 2002 года.) Цитируя MSDN:

  

Оператор выражения должен иметь одну из следующих форм:

     

x бинарный оператор = expr

     

x++

     

++x

     

x--

     

--x

     

В предыдущих выражениях: x является lvalue выражение со скалярным типом. expr - это выражение со скалярным типом, и оно не ссылается на объект, обозначенный x. binop не является перегруженным оператором и является одним из +, *, -, /, &, ^, |, << или >>.

Я рекомендую использовать atomic, когда вы можете, и именовал критические разделы в противном случае. Называть их важно; таким образом вы избежите головной боли отладки.

ответил pelesl 1 52013vEurope/Moscow11bEurope/MoscowFri, 01 Nov 2013 23:31:22 +0400 2013, 23:31:22
0

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

  

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

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

1. Define a variable called lock.
2. For each thread:
   2.1. Read the lock.
   2.2. If lock == 0, lock = 1 and goto 3    // Try to grab the lock
       Else goto 2.1    // Wait until the lock is released
3. Do something...
4. lock = 0    // Release the lock

Данный алгоритм может быть реализован на аппаратном языке следующим образом. Мы будем использовать один процессор и проанализируем поведение блокировок в этом. Для этой практики давайте предположим один из следующих процессоров: MIPS , Альфа , ARM или Power .

try:    LW R1, lock
        BNEZ R1, try
        ADDI R1, R1, #1
        SW R1, lock

Эта программа вроде бы в порядке, но это не так. Приведенный выше код страдает от предыдущей проблемы; синхронизация . Давайте найдем проблему. Предположим, что начальное значение блокировки равно нулю. Если два потока запускают этот код, один может достигнуть SW R1, заблокировать до того, как другой прочитает переменную lock . Таким образом, они оба думают, что блокировка свободна. Чтобы решить эту проблему, есть другая инструкция, а не простые LW и SW . Это называется инструкциями Read-Modify-Write . Это сложная инструкция (состоящая из подинструкций), которая гарантирует, что процедура получения блокировки выполняется только одним одним потоком одновременно. Отличие Read-Modify-Write по сравнению с простыми инструкциями Read и Write заключается в том, что он использует другой способ загрузки и Хранение . Он использует LL (Load Linked) для загрузки переменной блокировки и SC (Store Conditional) для записи в переменную блокировки. Дополнительный Ссылочный регистр используется, чтобы гарантировать, что процедура получения блокировки выполняется одним потоком. Алгоритм приведен ниже.

1. Define a variable called lock.
2. For each thread:
   2.1. Read the lock and put the address of lock variable inside the Link Register.
   2.2. If (lock == 0) and (&lock == Link Register), lock = 1 and reset the Link Register then goto 3    // Try to grab the lock
       Else goto 2.1    // Wait until the lock is released
3. Do something...
4. lock = 0    // Release the lock

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

Основное различие между критическим и атомарным заключается в том, что:

  

Зачем использовать блокировки (новую переменную), в то время как мы можем использовать фактическую переменную (над которой мы выполняем операцию), в качестве переменной блокировки?

Использование переменной new для блокировок приведет к критическому разделу , а переменная actual в качестве Блокировка приведет к концепции атомарного . Критическая секция полезна, когда мы выполняем много вычислений (более одной строки) для фактической переменной. Это связано с тем, что если результат этих вычислений не может быть записан в фактическую переменную, вся процедура должна быть повторена для вычисления результатов. Это может привести к низкой производительности по сравнению с ожиданием снятия блокировки перед входом в область с высокой вычислительной мощностью. Таким образом, рекомендуется использовать директиву atomic всякий раз, когда вы хотите выполнить одно вычисление (x ++, x--, ++ x, --x и т. Д.) И использовать критический директива, когда интенсивный раздел выполняет более сложную вычислительную область.

ответил alighdev 2 Mayam18 2018, 11:13:06
0

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

ответил Mahesh 26 J000000Friday13 2013, 11:54:24
0

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

критическая секция - это блокировка блока кода

Хороший компилятор переведет ваш второй код так же, как и первый

ответил Wissam Y. Khalil 18 WedEurope/Moscow2013-12-18T21:17:04+04:00Europe/Moscow12bEurope/MoscowWed, 18 Dec 2013 21:17:04 +0400 2013, 21:17:04

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132