インテル® C++ コンパイラー XE 13.1 ユーザー・リファレンス・ガイド
特定のメモリー位置をアトミックに更新し、複数のスレッドが同時に読み取り/書き込みを行う危険性を回避します。
#pragma omp atomic [ read | write | update | capture ] |
expression-stmt
OR
#pragma omp atomic capture |
structured-block
アトミック領域のバインドスレッドは、すべてのスレッドです。アトミック領域は、プログラム中のすべてのスレッドがその所属チームに関係なく、複数のアトミック領域によってアクセスされる同じメモリー位置 x への排他アクセスを徹底します。
#pragma omp atomic には、「プログラム全体を通して、メモリー位置 x へのすべてのアトミックアクセスは、同じ型と型パラメーターでなければならない」という制限があります。
次の表は、atomic 構造でそれぞれの節を指定した場合の影響を説明したものです。
節 |
結果 |
---|---|
read | ネイティブマシンのワードサイズに関係なく、メモリー位置 x へのアトミックな読み取りが行われます。 |
write | ネイティブマシンのワードサイズに関係なく、メモリー位置 x へのアトミックな書き込みが行われます。 |
[update] | 指定された演算子または組込み関数を使用して、メモリー位置 x がアトミックに更新されます。 次の規則も適用されます。
|
capture | 指定された演算子または組込み関数でメモリー位置 x がアトミックに更新されます。また、アトミックな更新時に、メモリー位置 x の元の値または最後の値もキャプチャーされます。 次の規則も適用されます。
メモリー位置 x の読み取りと書き込みの間にタスク・スケジューリング・ポイントはありません。 |
2 つ以上の atomic 構造を組み合わせることで、メモリー位置 x への排他アクセスを行うことができます。
同期処理をせずに 2 つのスレッドが同じ共有変数にアクセスし、少なくとも一方のスレッドがその変数を変更する場合、データ競合が発生し、予期しない結果を引き起こすことがあります。 競合を回避するには、メモリー位置 x へ並列にアクセスする可能性がある場合、atomic 構造を使用して該当するすべてのアクセスを保護する必要があります。
アトミック領域は、OpenMP* のロックが実行タスクによって保有されている間、または reduction 節の実行中は、critical 領域あるいは ordered 領域であっても、領域外の同じメモリー位置 x への排他アクセスを保証しません。
ただし、ほかの OpenMP* の同期を使用することで、排他アクセスを指定することができます。 例えば、x への一連のアトミックな更新の後に barrier プラグマを指定することで、それ以降のアクセスがアトミックアクセスと競合しないようにできます。
#pragma omp atomic update k += n*mass; // k is updated atomically
#pragma omp atomic read tmp = c; // c is read atomically
#pragma omp atomic write count = n*m; // count is written atomically
#pragma omp atomic capture { d = v; v += n; } // atomically update v, but capture original value of v in d
#pragma omp atomic capture { o = c++; } // capture the old value of c, then increment c