OpenMP* によるプログラミング

インテル® コンパイラーは、OpenMP 宣言子を含む Fortran プログラムを入力ファイルとして処理し、マルチスレッド・バージョンのコードを生成します。並列プログラムが実行を開始する際に存在する単一スレッドは、初期スレッドと呼ばれます。

初期スレッドは、並列領域に到達すると、チームのマスタースレッドになることができます。並列領域に到達するまで、初期スレッドはシーケンシャルに処理を続行します。

並列領域

並列領域とは、1 つのスレッドチームによって並列に実行されなければならない 1 ブロックのコードです。OpenMP API では、並列構造は OpenMP 宣言子 PARALLEL をコードセグメントの最初に、宣言子 END PARALLEL を最後に配置して定義されます。このように境界のあるコードセグメントは、並列実行が可能です。

コードの構造ブロックとは、最初と最後に単一の入口/出口ポイントを持つ、1 つまたは複数の実行文の集まりです。

インテル® Visual Fortran コンパイラーはワークシェアリング構造および同期化構造をサポートします。これらの各構造は、特定の 1 つまたは 2 つの OpenMP 宣言子と、囲まれた、または後続するコードの構造ブロックから構成されます。

並列領域の最後で、スレッドはすべてのチームメンバーが到達するまで待機します。そして、チームは論理的になくなり (次の並列領域で再利用されることもあります)、マスタースレッドは次の並列領域が検出されるまでシーケンシャルに処理を続行します。

ワークシェアリング構造

ワークシェアリング構造は、それを囲む並列領域に入る時点で作成されたチームメンバー間で、囲まれたコード領域の実行を分割します。マスタースレッドが並列領域に入ると、スレッドチームが形成されます。並列領域の最初から開始して、ワークシェアリング構造が検出されるまで、すべてのチームメンバーによってコードは実行されます。ワークシェアリング構造は、チームのメンバー間で、囲まれたコード領域の実行を分割します。

OpenMP の SECTIONS または DO 構造は、その囲まれた作業を現在のチームのスレッド間に分配するため、ワークシェアリング構造として定義されます。ワークシェアリング構造は、並列領域の動的実行中である場合にのみ分配されます。ワークシェアリング構造が並列領域の記述範囲内にあれば、チームのメンバー間で処理を分配することにより、そのワークシェアリング構造は常に実行されます。ワークシェアリング構造が並列領域に字句的 (明示的) に囲まれていない場合 (つまり、構造が孤立 (orphan) している場合)、そのワークシェアリング構造は、最も近い動的範囲の並列領域のチームメンバー間に分配されます (これが存在する場合)。動的範囲の並列領域が存在しない場合、構造はシーケンシャルに実行されます。

1 つのスレッドがワークシェアリング構造の最後に到達すると、構造内のすべてのチームメンバーが処理を終了するまで待機する場合があります。ワークシェアリング構造によって定義されたすべての処理が終了すると、チームはワークシェアリング構造を出て、後に続くコードの実行を続行します。

並列/ワークシェアリング複合構造とは、ワークシェアリング構造を 1 つだけ含む並列領域を示します。

並列処理宣言子グループ

並列処理宣言子には次のグループが含まれます。

並列領域宣言子

ワークシェアリング構造宣言子

並列/ワークシェアリング複合構造宣言子

並列/ワークシェアリング複合構造は、単一のワークシェアリング構造が含まれる並列領域を指定するための短縮形を提供します。並列/ワークシェアリング複合構造は次のとおりです。

同期化構造および MASTER 宣言子

同期化とは、共有データの一貫性を保証し、スレッド間の並列実行を調整するスレッド間通信です。データがアクセスされる際にすべてのスレッドが同じ値を取得する場合、スレッドのチームの共有データは一貫しています。同期化構造は、共有データの一貫性を保証するために使用されます。

OpenMP の同期化宣言子には、CRITICALORDEREDATOMICFLUSH および BARRIER があります。

宣言子

使用方法

CRITICAL

並列領域またはワークシェアリング構造内では、一度に 1 つのスレッドのみが CRITICAL 構造のコードを実行することができます。

ORDERED

DO または SECTIONS 構造とともに使用され、コード部分を順次実行します。

ATOMIC

他のスレッドに割り込まれずにメモリー位置を更新するために使用されます。

FLUSH

チーム内のすべてのスレッドが一貫性のあるメモリーのビューを持つために使用されます。

BARRIER

コード内の特定の位置ですべてのチームのメンバーが集合するために使用します。BARRIER を実行する各チームのメンバーは、他のメンバーが到達するまで BARRIER で待機します。ワークシェアリングまたは他の同期化構造内では、デッドロックの可能性があるため BARRIER を使用することはできません。

MASTER

マスタースレッドで実行するために使用します。

詳細は、「OpenMP* 宣言子と節の概要」のリストを参照してください。

データの共有

データの共有は、SHARED および PRIVATE 節を使用して、並列領域またはワークシェアリング構造の最初で指定されます。SHARED 節に含まれているすべての変数は、チームメンバー間で共有されます。アプリケーションでは次の手順が必要となります。

また、SHARED および PRIVATE 変数に加えて、THREADPRIVATE 宣言子を使用することで個々の変数と共通ブロック全体をプライベート化することができます。

孤立宣言子

OpenMP には、並列宣言子の表現力を大幅に向上する孤立化と呼ばれる機能が含まれています。孤立化では、並列領域に関連付けられている宣言子が 1 つのプログラムユニットの記述範囲内にある必要がありません。CRITICALBARRIERSECTIONSSINGLEMASTERDO および TASK などの宣言子は、ランタイム時に、囲まれた並列領域に動的に "バインド" し、プログラムユニット内に出現することができます。

孤立宣言子は、コードに最小限の変更を行うだけで、既存のコードを並列処理することができます。また、孤立化は、1 つの並列領域を、呼び出されたサブルーチン内にある複数の DO 宣言子とバインドすることでパフォーマンスの向上を可能にします。次のコードセグメントを参照してください。

subroutine phase1

  integer :: i

  !$OMP DO PRIVATE(i) SHARED(n)

  do i = 1, 200

    call some_work(i)

  end do

  !$OMP END DO

end

subroutine phase2

  integer :: j

  !$OMP DO PRIVATE(j) SHARED(n)

  do j = 1, 100

    call more_work(j)

  end do

  !$OMP END DO

end

program par

  !$OMP PARALLEL

  call phase1

  call phase2

  !$OMP END PARALLEL

end program par

孤立宣言子の使用規則

次に示す孤立宣言子の使用規則が適用されます。

OpenMP 処理を行うコードの準備

OpenMP を使用するためにコードを準備するには、次の段階と手順に従ってください。一般的に、最初の 2 つの段階は単一プロセッサー・システムまたはマルチプロセッサー・システムのいずれでも行うことができますが、その後の段階は通常、デュアルコア・プロセッサー・システムおよびマルチプロセッサー・システムで行います。

OpenMP 宣言子を挿入する前に

OpenMP 並列宣言子を挿入する前に、次の方法でコードが安全に並列実行されることを確認してください。

解析

解析の主な手順は次のとおりです。


  1. プログラムのプロファイルを作成して、最も多くの時間が費やされている箇所を見つけます。この箇所は、並列処理の恩恵が最も得られるプログラムの部分です。この段階は、基本的な PGO オプションを使用して行うことができます。

  2. プログラムが入れ子されたループを含む場合は、常に繰り返し間の依存関係が少ない、最外ループを選択します。

再編成

OpenMP を正しく実装するためにプログラムを再編成するには、次のいくつか、またはすべてを実行します。

チューニング

チューニング・プロセスでは、SCHEDULE 節または OMP_SCHEDULE 環境変数を使用して、クリティカル・セクションのシーケンシャル・コードを最小化し、負荷のバランスを図ります。

Note icon

この手順は通常、デュアルコア・プロセッサー・システムおよびマルチプロセッサー・システムで行います。