次の方法で共有


1.3 実行モデル

OpenMP は、fork-join モデルの並列実行を採用しています。この fork-join モデルはさまざまな問題に対応しますが、大規模な配列ベースのアプリケーション用に、多少の修正が加えられています。OpenMP は、並列プログラム (複数スレッドが実行し、完全 OpenMP サポート ライブラリを使用) および順次プログラム (ディレクティブは無視、単純な OpenMP スタブ ライブラリを使用) の両方として正しく実行されるプログラムをサポートします。ただし、順次実行では正しく動作しないプログラムを開発することもできます。さらに、並列化の異なるレベル付けにより、関連付けられている数値演算の違いで異なる数値結果を得ることもできます。たとえば、逐次加算リダクションに、並列リダクションとは異なる加算の関連付けパターンを持たすことができます。これらの異なる関連付けにより、浮動小数点加算の結果を変えることができます。

OpenMP C/C++ API で記述されたプログラムは、マスタ スレッドと呼ばれるシングル スレッドで実行を開始します。マスタ スレッドは、最初の parallel コンストラクトが現れるまでシリアル領域で実行します。OpenMP C/C++ API では、parallel ディレクティブが parallel コンストラクトを構成します。parallel コンストラクトが現れると、マスタ スレッドがスレッド チームを作成し、マスタ スレッドがそのチームのマスターになります。チーム内の各スレッドは、work-sharing コンストラクト以外の並行領域の動的範囲内でステートメントを実行します。Work-sharing コンストラクトは、チーム内のすべてのスレッドによって同じ順番で発生する必要があります。そして、関連付けられている構造化ブロック内のステートメントは 1 つ以上のスレッドによって実行されます。nowait 句を持たない work-sharing コンストラクトの末尾に暗黙的に存在するバリアが、チーム内のすべてのスレッドによって実行されます。

あるスレッドが共有オブジェクトを変更すると、これは、自身の実行環境に影響するだけでなく、プログラム内の他のスレッドの実行環境にも影響します。そのオブジェクトが揮発性であると宣言されている場合に限り、その変更は、他のスレッドの 1 つから見て、ベース言語で定義されている次のシーケンス ポイントで完了します。それ以外の場合は、変更は、変更したスレッド、次に (または同時に) 他のスレッドが、そのオブジェクトを暗黙的にまたは明示的に指定する flush ディレクティブを検出した後に、完了します。他の OpenMP ディレクティブによる暗黙的な flush ディレクティブでは副作用を十分に制御できない場合には、プログラマが明示的に flush ディレクティブを付け加える必要があります。

parallel コンストラクトの末尾では、チーム内のスレッドが暗黙的なバリアで同期し、マスタ スレッドのみ実行を続けます。1 つのプログラム内に parallel コンストラクトをいくつでも指定できます。結果として、1 つのプログラムが実行中に何回もフォークと結合を繰り返す場合があります。

OpenMP C/C++ API では、parallel コンストラクト内から呼び出された関数内でディレクティブを使用できるようになっています。parallel コンストラクトの構文範囲内には現れないが動的範囲内には現れるディレクティブを、孤立したディレクティブと呼びます。孤立したディレクティブにより、プログラマは、順次プログラムに対して最小限の変更を行うだけで、プログラムの主要な部分を並列実行させることができます。この機能により、プログラマはトップ レベルのプログラム コール ツリーで parallel コンストラクトを作成し、任意の呼び出される関数内で、実行を制御するディレクティブを使用できます。

同じファイルに書き込む C および C++ の出力関数を非同期で呼び出すと、複数のスレッドで書き込まれたデータが順不同で出力されます。同様に、同じファイルから読み込む入力関数を非同期で呼び出すと、順不同でデータが読み込まれます。各スレッドが別のファイルにアクセスする場合の非同期 I/O では、I/O 関数の逐次実行と同じ結果になります。