並列処理スレッドモデル

ここでは、並列化されたプログラム処理の説明と、並列プログラミングで使用される用語の定義を追加説明します。

実行フロー

前述したように、OpenMP* の C++ API コンパイラ・ディレクティブを持つプログラムは、単一のプロセスとして実行を開始します。これは、マスタスレッドの実行と呼ばれます。最初の並列コンストラクタが検出されるまで、マスタスレッドは、シーケンシャルに実行します。

OpenMP C++ APIでは、#pragma omp parallel ディレクティブは、並列コンストラクタを定義します。マスタスレッドが並列コンストラクタを検出すると、そのマスタスレッドがチームのマスタとなるように、スレッドのチームを作成します。並列コンストラクタに囲まれたプログラム文は、チーム内の各スレッドごとに並列して実行されます。これらの文は、囲まれた文の中から呼び出されるルーチンを含みます。

コンストラクタ内で字句的に囲まれた文は、コンストラクタの静的範囲を定義します。動的範囲は、コンストラクタ内から呼び出されるルーチンと同様に静的範囲を含みます。#pragma omp parallel ディレクティブが終了すると、チーム内のスレッドは同期化され、そのチームは消滅して、マスタスレッドのみが実行し続けます。チーム内の他のスレッドは、待機状態になります。単一プログラム内で並列コンストラクタは何回でも指定できます。結果として、プログラム実行中に、スレッドのチームは何度も生成され消滅します。

孤立ディレクティブの使用

並列コンストラクタ内で呼び出されたルーチンで、ディレクティブを使用することができます。並列コンストラクタの字句範囲ではなく、動的範囲のディレクティブは、孤立ディレクティブと呼ばれます。孤立ディレクティブは、プログラムのシーケンシャル・バージョンに最小限の変更を行うだけで、プログラムの主要部分を並列に実行できます。この機能を使用すると、プログラムの最上位レベルで並列コンストラクタをコーディングでき、ディレクティブを使用して呼び出されるすべてのルーチンの実行を制御することができます。次に例を示します。

int main(void)

{

...

#pragma omp parallel

{

phase1();

}

}

 

void phase1(void)

{

...

 

#pragma omp for private(i) shared(n)

for(i=0; i < n; i++)

{

some_work(i);

}

}

並列範囲が字句的に指定されていないので、これが孤立ディレクティブとなります。

データ環境ディレクティブ

データ環境ディレクティブは、並列コンストラクタの実行中にデータ環境を制御します。並列およびワークシェアリング構造内でデータ環境を制御できます。ディレクティブとディレクティブのデータ環境節を使用して次のことが可能です。

複数のディレクティブ節を使用して、変数のデータスコープ属性を指定したコンストラクタの継続期間中にその属性を制御することができます。ディレクティブでデータスコープ属性節を指定しない場合、ディレクティブに影響を受ける変数のデフォルトは SHARED になります。

並列処理モデルの疑似コード

一般的な OpenMP ディレクティブをいくつか使用した疑似プログラムのサンプルには、次のものがあります。この例ではまた、シリアル領域と並列領域の相違も示しています。

main() { // Begin serial execution
 ... // Only the master thread executes
#pragma omp parallel // Begin a Parallel Construct, form
 { // a team. This is Replicated Code
  ... // (each team member executes
  ... // the same code)
  //
#pragma omp sections    // Begin a Worksharing Construct
 { //
  #pragma omp section // One unit of work
   {...} //
  #pragma omp section // Another unit of work
   {...} //
 } // Wait until both units of work complete
 ... // More Replicated Code
  //
 #pragma omp for nowait // Begin a Worksharing Construct;
  for(...) { // each iteration is unit of work
  //
   ... // Work is distributed among the team members
  //
 } // End of Worksharing Construct;
  // nowait was specified, so
  // threads proceed
  //
 #pragma omp critical // Begin a Critical Section
 { //
  ... // Replicated Code, but only one
  // thread can execute it at a
 } // given time
 ... // More Replicated Code
  //
 #pragma omp barrier // Wait for all team members to arrive
 ... // More Replicated Code
  //
} // End of Parallel Construct;
  // disband team and continue
  // serial execution
  //
... // Possibly more Parallel constructs
  //
} // End serial execution