2.6.4 atomic コンストラクト
atomic ディレクティブは、特定のメモリ位置が複数のスレッドによって同時に書き込まれるのを防ぎ、アトミック更新されるように指定します。atomic ディレクティブの構文は次のとおりです。
#pragma omp atomic new-line
expression-stmt
式ステートメントは、次のいずれかの形式である必要があります。
x binop= expr
x++
++x
x--
--x
上記の式に関する説明は以下のとおりです。
x は、スカラ型の左辺値式です。
expr は、x で指定されるオブジェクトを参照しないスカラ型の式です。
binop はオーバーロードされた演算子ではなく、+、*、-、/、&、^、|、<<、または >> のいずれかです。
実装が、すべての atomic ディレクティブを、同じ一意の名前を持つ critical ディレクティブと置き換えるかどうかは、実装によって定義されていますが、atomic ディレクティブの方が最適化の点で優れています。通常、最小限のオーバーヘッドでアトミック更新を実行できるハードウェア命令を使用できます。
x によって指定されるオブジェクトの読み込みと格納だけがアトミックとなります。expr の評価はアトミックに行われません。競合状態を避けるために、その位置に対して並列に行われるすべての更新は、競合状態が起こらないと判明しているものを除いて、atomic ディレクティブで保護する必要があります。
atomic ディレクティブに対する制限は次のとおりです。
- そのプログラムでの格納位置 x へのすべてのアトミック参照は、互換性のある型を持っていることが必要です。
例:
extern float a[], *p = a, b;
/* Protect against races among multiple updates. */
#pragma omp atomic
a[index[i]] += b;
/* Protect against races with updates through a. */
#pragma omp atomic
p[i] -= 1.0f;
extern union {int n; float x;} u;
/* ERROR - References through incompatible types. */
#pragma omp atomic
u.n++;
#pragma omp atomic
u.x -= 1.0f;