同期化構造とは、共有データの一貫性を保証し、スレッド間の並列実行を調整するのに使用されます。
同期化構造の宣言子は次のとおりです。
これらの宣言子についての詳細は、「OpenMP* Fortran Compiler Directives」(英語) を参照してください。
ATOMIC 宣言子を使用して、特定のメモリー・ロケーションをアトミックに更新し、同時に複数のスレッドによる書き込みの危険性を回避するようにします。
この宣言子は、直後に続く文にのみ適用され、次の形式のいずれかでなければなりません。
形式 |
説明 |
---|---|
x = x operator expr |
x は、組み込み型のスカラー変数です。 |
x = expr operator x |
expr は、x を参照しないスカラー式です。 |
x = intrinsic (x, expr) |
intrinsic は、MAX、MIN、IAND、IOR、または IEOR のいずれかです。 |
x = intrinsic (expr, x) |
operator は、+、*、-、/、.AND.、.OR.、.EQV. または .NEQV. のいずれかです。 |
この宣言子は、代入に関して、クリティカル・セクションで行われる最適化以上の最適化を可能にします。クリティカル・セクションで文を囲むことによって、すべての ATOMIC 宣言子を置換することができます。これらすべてのクリティカル・セクションは、同一で一意な名前を使用する必要があります。
x のロードとストアのみがアトミックです。expr の評価は、アトミックではありません。競合状態を避けるには、競合状態ではないことがわかっているロケーションを除いて、そのロケーションのすべての並列の更新において、ATOMIC 宣言子を使用して保護する必要があります。intrinsic 関数、operator 演算子、および代入は、組み込みの関数、演算子および代入でなければなりません。
次の制限は、ATOMIC 宣言子に適用されます: ストレージ・ロケーション x へのすべての参照は、同じ型のパラメーターでなければなりません。
次の例では、Y のロケーションの集合は、アトミックに更新されます。
例 |
---|
!$OMP ATOMIC Y = Y + B(I) |
並列領域内ですべてのスレッドを同期化するには、BARRIER 宣言子を使用します。この宣言子は、PARALLEL 宣言子により定義される並列領域内でのみ使用できます。BARRIER 宣言子は、DO、PARALLEL DO、SECTIONS、PARALLEL SECTIONS、SINGLE 構造内では使用できません。
各スレッドは、すべてのスレッドが宣言子に到達するまで BARRIER 宣言子で待機します。
次の例では、BARRIER 宣言子は、すべてのスレッドが最初のループを実行し、2 番目のループの実行が安全に行われることを保証します。
例 |
---|
!$OMP PARALLEL !$OMP DO PRIVATE(i) DO i = 1, 100 b(i) = i END DO !$OMP BARRIER !$OMP DO PRIVATE(i) DO i = 1, 100 a(i) = b(101-i) END DO !$OMP END PARALLEL |
CRITICAL および END CRITICAL 宣言子を使用して、クリティカル・セクションとして参照されるコードブロックへのアクセスを、一度に 1 つのスレッドに制限します。
スレッドは、同じ名前を持つクリティカル・セクションを実行するチーム内の他のスレッドがなくなるまで、クリティカル・セクションの最初で待機します。
スレッドが、クリティカル・セクションに入ると、ラッチ変数がクローズに設定され、他のスレッドは、ロックアウトされます。END CRITICAL 宣言子でクリティカル・セクションから出ると、ラッチ変数は、オープンに設定され、別のスレッドがクリティカル・セクションにアクセスできるようになります。
クリティカル・セクションの名前を CRITICAL 宣言子で指定した場合、END CRITICAL 宣言子でも同じ名前を指定する必要があります。CRITICAL 宣言子の名前を指定しない場合、END CRITICAL 宣言子の名前を指定することはできません。
名前を指定されていないすべての CRITICAL 宣言子は、同じ名前にマップします。クリティカル・セクションの名前は、プログラムに対してグローバルです。
次の例では、複数の CRITICAL 宣言子が含まれ、1 つのタスクがキューから取り出されて処理されるキューイングのモデルを示しています。複数のスレッドが同じタスクをキューから取り出さないために、デキューの操作はクリティカル・セクションになければなりません。この例では、2 つの独立したキューがあるため、各キューは、それぞれ X_AXIS と Y_AXIS という異なる名前を持つ CRITICAL 宣言子によって保護されます。
例 |
---|
!$OMP PARALLEL DEFAULT(PRIVATE),SHARED(X,Y) !$OMP CRITICAL(X_AXIS) CALL DEQUEUE(IX_NEXT, X) !$OMP END CRITICAL(X_AXIS) CALL WORK(IX_NEXT, X) !$OMP CRITICAL(Y_AXIS) CALL DEQUEUE(IY_NEXT,Y) !$OMP END CRITICAL(Y_AXIS) CALL WORK(IY_NEXT, Y) !$OMP END PARALLEL |
FLUSH 宣言子を使用して、メモリーの一貫性のあるビューが提供される同期ポイントを識別します。スレッドから見える変数は、このポイントでメモリーに書き戻されます。
このポイントでスレッドから見えるすべての変数のフラッシュを避けるには、フラッシュする名前付きの変数をカンマ区切りのリストに含めます。次の例では、FLUSH 宣言子を使用して、変数 ISYNC のスレッド 0 とスレッド 1 の Point To Point (ポイント間) の同期化を示します。
例 |
---|
!$OMP PARALLEL DEFAULT(PRIVATE),SHARED(ISYNC) IAM = OMP_GET_THREAD_NUM() ISYNC(IAM) = 0 !$OMP BARRIER CALL WORK() ! Synchronize With My Neighbor ISYNC(IAM) = 1 !$OMP FLUSH(ISYNC) ! Wait Till Neighbor Is Done DO WHILE (ISYNC(NEIGH) .EQ. 0) !$OMP FLUSH(ISYNC) END DO . . . !$OMP END PARALLEL |
MASTER および END MASTER 宣言子を使用して、マスタースレッドのみが実行するコードブロックを識別します。
チームの他のスレッドは、コードをスキップして実行を続けます。END MASTER 宣言子には、暗黙的なバリアはありません。次の例では、マスタースレッドのみが OUTPUT と INPUT ルーチンを実行します。
例 |
---|
!$OMP PARALLEL DEFAULT(SHARED) CALL WORK(X) !$OMP MASTER CALL OUTPUT(X) CALL INPUT(Y) !$OMP END MASTER CALL WORK(Y) !$OMP END PARALLEL |
ORDERED 宣言子を使用する場合は、DO 宣言子でも ORDERED 節を指定する必要があります。
オーダードセクションには、一度に 1 つのスレッドのみがループの繰り返し順序で入ることができます。次の例では、インデックスをシーケンシャルに出力します。
例 |
---|
!$OMP DO ORDERED,SCHEDULE(DYNAMIC) DO I=LB,UB,ST CALL WORK(I) END DO SUBROUTINE WORK(K) !$OMP ORDERED WRITE(*,*) K !$OMP END ORDERED END |