Две директивы совершенно разные.
single
не предоставляет никакого механизма, относящегося к взаимному исключению или инструкции atomi c. В результате секция single
может работать с общей переменной, измененной другими потоками. Вы сбиты с толку, потому что вы, вероятно, предполагаете, что другие потоки ничего не делают в разделе single
. Это не верно. Действительно, потоки могут завершать sh a parallel for
(или другой раздел single
) с закрытием nowait
или могут также создавать задачи OpenMP, выполняемые во время раздела single
и т. Д. c. Вот пример:
#pragma omp parallel
{
...
// This section does not wait for others threads
#pragma omp master
{
// some computation
int a = rand();
// some computation
}
// This section wait for others threads only at the end
#pragma omp single
{
// some computation
int b = rand();
// some computation
}
...
}
В приведенном выше коде два вызова rand
могут выполняться параллельно (поскольку секция master
может выполняться одним потоком, в то время как другой поток запускает * 1015). * раздел). Поскольку rand
не является потокобезопасным, это может привести к неопределенным результатам (возможно, из-за гонки). Кроме того, обратите внимание, что использование директивы single
не приводит к вызову rand
atomi c.
. Чтобы избежать условий гонки, вы можете использовать такие директивы синхронизации, как barrier
или * 1022. *. Вы также можете использовать взаимное исключение, используя инструкции critical
или atomi c, используя atomic
. Следует избегать директив синхронизации (когда это возможно), поскольку они часто вызывают проблемы масштабируемости. atomic
инструкции могут применяться только в определенных c случаях. Например, вы не можете использовать директивы atomic
для вызовов rand
в приведенном выше коде. Однако вы можете использовать critical
разделы для защиты этих вызовов (сохраняя при этом разделы single
и master
, которые могут выполняться параллельно).
atomic
предпочтительнее, чем critical
, когда оба имеют смысл, поскольку накладные расходы на инструкции atomic
обычно меньше. Директиву atomic
нельзя заменить только директивой single
, поскольку atomic
выполняется каждым потоком параллельной секции, а секция single
- только одной.