次の方法で共有


1.イントロダクション

このドキュメントでは、C プログラムと C++ プログラムで共有メモリの並列処理を指定するために使用可能なコンパイラ ディレクティブ、ライブラリ関数、および環境変数について説明します。 このドキュメントに記載されている機能は、総称して OpenMP C/C++ アプリケーション プログラム インターフェイス (API) と呼ばれています。 この仕様書の目的は、さまざまなベンダーの共有メモリ アーキテクチャ間でプログラムを移植できるようにする並列プログラミングのモデルを提供することです。 多くのベンダーのコンパイラが OpenMP C/C++ API をサポートしています。 OpenMP Fortran アプリケーション プログラム インターフェイスなど、OpenMP に関する詳細情報については、次の Web サイトを参照してください。

https://www.openmp.org

このドキュメントで定義するディレクティブ、ライブラリ関数、および環境変数を使用すると、移植性を確保しながら、並列プログラムを作成および管理できます。 ディレクティブは、単一プログラム複数データ (SPMD) コンストラクト、作業共有コンストラクト、および同期コンストラクトを使用して、C および C++ のシーケンシャル プログラミング モデルを拡張します。 また、データの共有とプライベート化もサポートします。 OpenMP C および C++ API をサポートするコンパイラには、すべての OpenMP コンパイラ ディレクティブをアクティブにして解釈可能にするためのコマンドライン オプションが組み込まれています。

1.1 スコープ

この仕様書では、ユーザー向けの並列処理についてのみ説明し、コンパイラとランタイム システムがプログラムを並列に実行するために取るアクションを明示的に定義します。 OpenMP C および C++ の実装では、依存関係、競合、デッドロック、競合状態、またはその他の不正なプログラムの実行につながる問題を確認する必要はありません。 OpenMP C および C++ API コンストラクトを使用するアプリケーションが正しく実行されることを確認する責任はユーザーにあります。 コンパイラが生成する自動並列化と、このような並列処理を支援するコンパイラへのディレクティブについては、このドキュメントでは説明しません。

1.2 用語の定義

次の用語は、このドキュメントで使用されます。

  • barrier

    チーム内のすべてのスレッドが到達する必要がある同期ポイント。 各スレッドは、チーム内のすべてのスレッドがこのポイントに到着するまで待機します。 ディレクティブによって識別される明示的なバリアと実装によって作成される暗黙的なバリアがあります。

  • construct

    コンストラクトはステートメントです。 ディレクティブとその後ろの構造化ブロックで構成されます。 コンストラクトに含まれないディレクティブもあります (付録 Copenmp-directive を参照してください)。

  • directive

    C または C++ #pragma の後ろに omp 識別子、その他のテキスト、および改行が続きます。 ディレクティブは、プログラムの動作を指定します。

  • 動的エクステント

    字句エクステント内のすべてのステートメントと、字句エクステント内のステートメントの実行結果として実行される関数内のすべてのステートメントが含まれます。 動的エクステントは、リージョンとも呼ばれます。

  • 字句エクステント

    構造化ブロック内に字句として保持されるステートメント。

  • マスター スレッド

    並列リージョンが入力されたときにチームを作成するスレッド。

  • 並列リージョン

    OpenMP 並列コンストラクトにバインドされ、複数のスレッドによって実行されるステートメント。

  • private

    プライベート変数は、参照を構築するスレッドに固有のストレージのブロックを指定します。 変数がプライベートであることを指定する方法はいくつかあります。並列リージョン内での定義、threadprivate ディレクティブ、privatefirstprivatelastprivate、または reduction 句、あるいは for または parallel for ディレクティブの直後の for ループ内での for ループ制御変数としての変数の使用。

  • region

    動的エクステント。

  • 逐次リージョン

    並列リージョンの動的な範囲外のマスター スレッドによってのみ実行されるステートメント。

  • serialize

    次の条件で並列コンストラクトを実行するには:

    • 1 つのスレッド (並列コンストラクトのマスター スレッド) で構成されるスレッドのチーム

    • 構造化ブロック内のステートメントの実行の順次順序 (ブロックが並列コンストラクトの一部ではない場合と同じ順序)

    • omp_in_parallel() によって返される値に対する影響なし (入れ子になった並列コンストラクトの影響とは異なる)

  • 共有済み

    共有変数は、1 つのストレージ ブロックを指定します。 この変数にアクセスするチーム内のすべてのスレッドも、この 1 つのストレージ ブロックにアクセスします。

  • 構造化ブロック

    構造化ブロックは、1 つの入口と 1 つの出口を持つステートメント (単一または複合) です。 ステートメントにジャンプしたり、ステートメントからジャンプしたりする場合は、そのステートメントが構造化ブロックです (このルールには longjmp(3C) の呼び出しまたは throw の使用が含まれますが、exit の呼び出しは許可されます)。 実行が常に { を開いたときに始まり、} を閉じたときに終わる場合は、複合ステートメントが構造化ブロックです。 {} で囲むことによって得られる対応する複合ステートメントが構造化ブロックの場合は、式ステートメント、選択ステートメント、反復ステートメント、または try ブロックが構造化ブロックです。 ジャンプ ステートメント、ラベル付きステートメント、または宣言ステートメントは構造化ブロックではありません。

  • チーム

    1 つのコンストラクトの実行で協調する 1 つ以上のスレッド。

  • スレッド

    コントロールのシリアル フロー、プライベート変数のセット、および共有変数へのアクセス権を有する実行エンティティ。

  • 変数

    オプションで名前空間名によって修飾され、オブジェクトを指定する識別子。

1.3 実行モデル

OpenMP は、並列実行の fork-join モデルを使用します。 fork-join モデルはさまざまな問題を解決するのに役立ちますが、大規模な配列ベースのアプリケーションに合わせて調整されています。 OpenMP の目的は、並列プログラム (複数の実行スレッドと完全な OpenMP サポート ライブラリ) として両方を正常に実行するプログラムをサポートすることです。 また、逐次プログラム (無視されたディレクティブと単純な OpenMP スタブ ライブラリ) として正しく実行するプログラムにも対応しています。 ただし、連続して実行されたときに正しく動作しないプログラムが開発される可能性があります。 また、数値演算の関連付けの変更が原因で、並列処理の次数によって異なる数値結果が生成される可能性があります。 たとえば、逐次加減算では、加算の関連付けのパターンが並列加算と異なる場合があります。 これらの関連付けによって、浮動小数点加算の結果が異なる場合があります。

OpenMP C/C++ API で記述されたプログラムは、マスター スレッドと呼ばれる単一の実行スレッドとして実行を開始します。 マスター スレッドは、最初の並列コンストラクトが検出されるまで逐次リージョンで実行されます。 OpenMP C/C++ API では、parallel ディレクティブが並列コンストラクトを構成します。 並列コンストラクトが検出されると、マスター スレッドがスレッドのチームを作成し、マスターがチームのマスターになります。 チーム内の各スレッドは、並列リージョンの動的エクステント内のステートメントを実行します。ただし、作業共有コンストラクトは除きます。 チーム内のすべてのスレッドが同じ順序で作業共有コンストラクトを検出する必要があり、1 つ以上のスレッドが関連付けられた構造化ブロック内でステートメントを実行します。 nowait 句を使用せずに作業共有コンストラクトの最後で暗黙的に指定されるバリアは、チーム内のすべてのスレッドによって実行されます。

あるスレッドが共有オブジェクトを変更した場合は、そのスレッドの実行環境だけでなく、プログラム内の他のスレッドの実行環境にも影響します。 変更は、オブジェクトが揮発性として宣言されている場合にのみ、次のシーケンス ポイント (基本言語で定義されている) における別のスレッドの観点から完了することが保証されます。 そうでない場合は、変更が最初のスレッドの変更後に完了することが保証されます。 他のスレッドは、その後で (または同時に)、オブジェクトを (暗黙的または明示的に) 指定する flush ディレクティブを参照します。 他の OpenMP ディレクティブによって暗黙的に指定される flush ディレクティブが副作用の正しい順序を保証していない場合は、プログラマの責任で追加の明示的な flush ディレクティブを指定する必要があります。

並列コンストラクトが完了すると、チーム内のスレッドが暗黙的なバリアで同期され、マスター スレッドだけが実行を継続します。 1 つのプログラムで、任意の数の並列コンストラクトを指定できます。 その結果、プログラムは、実行中に何度もフォークおよび結合する可能性があります。

OpenMP C/C++ API を使用すると、プログラマは、並列コンストラクト内から呼び出される関数でディレクティブを使用できます。 並列コンストラクトの字句エクステント内に出現しないが、動的エクステント内に存在する可能性があるディレクティブは、孤立したディレクティブと呼ばれます。 孤立したディレクティブを使用すると、プログラマは、逐次プログラムに対する最小限の変更だけで、プログラムの大部分を並列で実行できます。 この機能を使用すると、プログラム呼び出しツリーの最上位レベルで並列コンストラクトをコーディングし、ディレクティブを使用して呼び出した関数のいずれかでの実行を制御できます。

同じファイルに書き込む C および C++ 出力関数の非同期呼び出しでは、複数のスレッドによって書き込まれたデータが非決定的な順序で出力に表示される可能性があります。 同様に、同じファイルから読み取る入力関数の非同期呼び出しでは、データが非決定的な順序で読み取られる可能性があります。 各スレッドが異なるファイルにアクセスするような I/O の非同期使用では、I/O 関数の逐次実行と同じ結果が生成されます。

1.4 準拠

OpenMP C/C++ API の実装は、第 1、2、3、4 章と付録 C に記載されているように、この仕様書のすべての要素のセマンティクスを認識して保持している場合に、OpenMP に準拠します。付録 A、B、D、E、F は情報提供のみを目的としており、仕様書の一部ではありません。 API のサブセットのみを含む実装は、OpenMP に準拠していません。

OpenMP C および C++ API は、実装によってサポートされる基本言語の拡張機能です。 基本言語がこのドキュメントに記載されている言語コンストラクトまたは拡張機能をサポートしていない場合は、OpenMP 実装でそれをサポートする必要はありません。

すべての標準 C および C++ ライブラリ関数と組み込み関数 (つまり、コンパイラが認識している関数) は、スレッドセーフである必要があります。 並列リージョン内の複数のスレッドによるスレッドセーフ関数の非同期使用では、未定義の動作が発生しません。 ただし、動作が逐次リージョンと同じではない場合があります (乱数生成関数がその例です)。

OpenMP C/C++ API は、特定の動作を実装定義として指定します。このような場合は、その動作を定義して文書化するために、準拠 OpenMP 実装が必要です。 実装定義の動作の一覧については、付録 E を参照してください。

1.5 標準リファレンス

  • ISO/IEC 9899:1999、情報技術 - プログラミング言語 - C。この OpenMP API 仕様書では、ISO/IEC 9899:1999 を C99 として参照しています。

  • ISO/IEC 9899:1990、情報技術 - プログラミング言語 - C。この OpenMP API 仕様書では、ISO/IEC 9899:1990 を C90 として参照しています。

  • ISO/IEC 14882:1998、情報技術 - プログラミング言語 - C++。 この OpenMP API 仕様書では、ISO/IEC 14882:1998 を C++ として参照しています。

この OpenMP API 仕様書で C が参照されている場合は、実装によってサポートされる基本言語への参照が行われます。

1.6 階層