Оператор-выражение
, где оператор-выражение должен иметь одну из следующих форм:
В предыдущих выражениях: x - переменная. выражение - должно быть выражением скалярного типа. binop - должен быть одним из следующих операторов: +, *, -, /, &, |, <<,или >>. По сути atomic и critical решают одну и ту же проблему, но директива atomic более эффективна, чем critical. Пример: Следующий пример исключает условие «гонки», т.е. одновременное изменение элемента x несколькими нитями, путем использования директивы atomic:
#pragma omp parallel for shared(x, y, n) for (i=0; i<n; i++) { #pragma omp atomic x[i] += work1(i); y[i] += work2(i); }
Преимущество использования директивы atomic в этом примере состоит в том, что директива позволяет изменить значения двух различных элементов x параллельно. Если вместо директивы atomic была бы использована директива critical, то все модификации элементов x должны были быть выполнены последовательно (хотя и в не гарантированном порядке). Заметим, что директива atomic приемлема только к оператору, непосредственно следующему за директивой. И как следствие, в этом примере, элемент y не модифицируется атомарно.
4. barrier выполняет явную синхронизацию работы всех нитей в группе. При достижении оператора barrier, каждая нить останавливается и ожидает, пока остальные нити достигнут этой точки, после чего все нити продолжают работать дальше в параллельном режиме. Синтаксис директивы barrier: #pragma omp barrier 5. flush Поскольку в современных параллельных вычислительных системах может использоваться сложная структура и иерархия памяти, пользователь должен иметь гарантии того, что в необходимые ему моменты времени каждая нить будет видеть единый согласованный образ памяти. Для этих целей и предназначена директива flush. flush определяет пересечение нитей (cross-thread) в точке оценки, где требуется гарантия того, что все нити в группе имеют одно и то же видение некоторых объектов памяти. Это означает, что предыдущие вычисления выражений, которые ссылаются на эти объекты памяти, были завершены, а последующие вычисления не начаты. Синтаксис директивы flush: #pragma omp flush [(список)] Все переменные, которые требуют синхронизации, должны быть перечислены в списке директивы. Если в этом списке присутствует указатель, то осуществляется сброс самого указателя, а не числового значения объекта, на который он указывает. Директива flush без списка синхронизирует все разделяемые переменные (такой способ синхронизации будет иметь значительные накладные расходы по сравнению с директивой flush со списком). Директива flush без списка может использоваться в директивах:
Директиву flush нельзя использовать, если присутствует оператор nowait (т.е. выполнение без синхронизации).
Ограничения к использованию директивы flush: 1. Переменная, определенная в директиве flush, не должна быть ссылкой. 2. программная конструкция, которая содержит директиву barrier, должна быть блоком (или составным оператором).
6. ordered - директивадолжна находиться внутри конструкций for или parallel for. Программный блок, непосредственно следующий за директивой ordered, выполняется в порядке, в котором итерации цикла выполнялись бы в последовательном режиме. Синтаксис директивы ordered: #pragma omp ordered
|