ここでは、並列化されたプログラム処理の説明と、並列プログラミングで使用される用語の定義を追加説明します。
OpenMP の C++ API コンパイラー宣言子を持つプログラムは、単一のプロセスとして実行を開始します。これは、マスタースレッドの実行と呼ばれます。最初の並列構造が検出されるまで、マスタースレッドは、シーケンシャルに実行します。
OpenMP C++ API では、#pragma omp parallel 宣言子は、並列構造を定義します。マスタースレッドが並列構造を検出すると、そのマスタースレッドがチームのマスターとなるように、スレッドのチームを作成します。並列構造に囲まれたプログラム文は、チーム内の各スレッドごとに並列して実行されます。これらの文は、囲まれた文の中から呼び出されるルーチンを含みます。
構造内で字句的に囲まれた文は、構造の静的範囲を定義します。動的範囲は、構造内から呼び出されるルーチンと同様に静的範囲を含みます。#pragma omp parallel 宣言子が検出されると、チーム内のスレッドはその時点で同期し、そのチームは消滅して、マスタースレッドのみが実行を続けます。チーム内の他のスレッドは、待機状態になります。単一プログラム内で並列構造は何回でも指定できます。結果として、プログラム実行中に、スレッドのチームは何度も生成され消滅します。
ワークロードがアプリケーションの (一定ではない) 入力に依存するアプリケーションでは、入力サイズが確認されるランタイム時まで、使用するスレッド数の決定を遅延します。スレッド数に影響を与えるワークロードの入力パラメーターには、行列のサイズ、データベースのサイズ、イメージ/ビデオのサイズおよび解像度、ツリーベースの構造体の階層の深さ/幅/種類、およびリストベースの構造体のサイズなどが含まれます。同様に、プロセッサー数が一定ではないシステムで実行するように設計されたアプリケーションでは、マシンサイズが確認されるアプリケーション・ランタイム時まで、使用するスレッド数の決定を延期します。
入力データから作業量を予期できないアプリケーションでは、適切なスレッド数を選択するために、測定ステップを取り入れて、ワークロードおよびシステムの特性を確認することを推奨します。測定結果は、ファイルシステムなど永久保管場所に格納することによって、(測定ステップのオーバーヘッドを抑え) 永続的に使用することができます。スレッドは、システム上のプロセッサー数以内で作成してください。プロセッサー数を超えるスレッドを作成すると、すべてのスレッドが同時にアクティブになった場合、オペレーティング・システムによるプロセッサーへの多重送信が発生し、パフォーマンスが最適化されません。
ライブラリーを開発する場合 (アプリケーション全体を開発する場合とは異なり)、ライブラリーによって使用されるスレッド数を簡単に選択できるメカニズムを使用してください。これは、より高度な並列化を使用している場合、ライブラリー内の並列化が必要ないためです。
最後に、OpenMP では並列領域で num_threads 節を使用して、使用するスレッド数を制御し、並列領域で if 節を使用してマルチスレッドを使用するかどうかを決定します。omp_set_num_threads 関数を使用することもできますが、その影響はグローバルで、現在の関数の処理後も (呼び出し元に対しても) 効力を持ち続けるため、特別かつ十分に理解された状況以外でこの関数を使用することは推奨していません。num_threads 節の効果はローカルであるため、呼び出し元の環境には影響しません。
並列構造内で呼び出されたルーチンで、宣言子を使用することができます。並列構造の字句範囲ではなく、動的範囲の宣言子は、孤立宣言子と呼ばれます。孤立宣言子は、プログラムのシーケンシャル・バージョンに最小限の変更を行うだけで、プログラムの主要部分を並列に実行できます。この機能を使用すると、プログラム・コール・ツリーの最上位レベルで並列構造をコーディングでき、宣言子を使用して呼び出されるすべてのルーチンの実行を制御することができます。次に例を示します。
例 1 |
---|
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); } } |
並列範囲が字句的に指定されていないので、これが孤立宣言子となります。
データ環境宣言子は、並列構造の実行中にデータ環境を制御します。
並列およびワークシェアリング構造内でデータ環境を制御できます。宣言子と宣言子のデータ環境節を使用して次のことが可能です。
THREADPRIVATE 宣言子を使用して、名前付き共通ブロックをプライベート化します。
THREADPRIVATE 宣言子の節を使用して、データスコープ属性を制御します。
データスコープ属性節:
COPYIN
DEFAULT
PRIVATE
FIRSTPRIVATE
LASTPRIVATE
REDUCTION
SHARED
複数の宣言子節を使用して、変数のデータスコープ属性を指定した構造の継続期間中にその属性を制御することができます。宣言子でデータスコープ属性節を指定しない場合、宣言子に影響を受ける変数のデフォルトは SHARED になります。
節の詳細は、OpenMP C/C++ バージョン 2.5 仕様 (http://www.openmp.org/specs) を参照してください。
例 2: 並列処理モデルの疑似コード |
---|
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 |