以下の OpenMP ディレクティブ文節を使用すると、
並列構文内の変数の有効範囲属性を指定できます。
また、本節の IF、NUM_THREADS、ORDERED、
および SCHEDULE 文節を
使用して、並列領域の並列環境を制御することもできます。
詳細については、詳細なディレクティブの説明を参照してください。
|
|
|
変数名または共通ブロック名を文節に複数回指定してはなりません。
共通ブロックのメンバーである変数、共通ブロック名、または変数名は、 次の例外を除いて、同じディレクティブの複数の文節に指定してはなりません。
変数の有効範囲を変更する文節を指定しない場合は、ディレクティブの 影響を受ける変数のデフォルト有効範囲は、SHARED になります。
並列領域の動的エクステント内で参照されるプロシージャーの中で 宣言された、SAVE または STATIC 属性を持つローカル変数には、 暗黙の SHARED 属性があります。 並列領域の動的エクステント内で参照されるプロシージャーの中で 宣言された、SAVE または STATIC 属性を持たないローカル変数には、 暗黙の PRIVATE 属性があります。
並列領域の動的エクステント内で参照されるプロシージャーの中で宣言された、 モジュールの共通ブロックおよび変数のメンバーには、 それらが THREADLOCAL または THREADPRIVATE 共通ブロックおよびモジュール変数である場合を除いて、 暗黙の SHARED 属性があります。
以下のような状況では、並列または作業共用構文が実行されている間、 ディレクティブの PRIVATE、FIRSTPRIVATE、LASTPRIVATE、 または REDUCTION 文節で使用される変数あるいは変数サブオブジェクトについて、 参照、定義、定義解除、関連付け状況の変更、割り振り状況の変更、または実引き数としての指定を行ってはなりません。
変数を PRIVATE、FIRSTPRIVATE、LASTPRIVATE、 または REDUCTION として宣言することができます。 この変数がすでに他の変数とストレージが関連している場合であってもそうです。 ストレージ関連付けが、EQUIVALENCE ステートメント または COMMON ブロックの中で宣言されている変数について 存在することがあります。PRIVATE、FIRSTPRIVATE、LASTPRIVATE、 または REDUCTION 変数とストレージが関連している変数の場合は、 次のようになります。
OpenMP Fortran API バージョン 2.0 は、PRIVATE 文節の変数 または変数サブオブジェクトが POINTER または ALLOCATABLE 属性を持つことができるようにします。 ポインターの関連付け状況は、スレッドが作成されたときと、スレッドが破棄されたときに未定義になります。 割り振り可能配列は、スレッド作成時に、 現在割り振られていないという割り振り状況になっている必要があります
+----------------------------------IBM 拡張----------------------------------+
XL Fortran は、FIRSTPRIVATE または LASTPRIVATE 文節の変数または変数サブオブジェクトが POINTER 属性を 持つことができるようにする拡張機能を提供します。 スレッド作成時の FIRSTPRIVATE ポインターの場合、ポインターの各コピーが オリジナルと同じ関連付け状況を受け取ります。 ポインターが LASTPRIVATE 文節で使用される場合、ポインターは、 最後の繰り返しまたは SECTION の終わりの関連付け状況を保持します。
+------------------------------End of IBM 拡張-------------------------------+
OpenMP Fortran API バージョン 2.0 標準との完全な準拠を維持するには、POINTER 変数は、PRIVATE 文節にのみ適用してください。
目的
COPYIN 文節を指定する場合、 各変数のマスター・スレッドのコピーまたは copyin_entity_list 内に宣言された共通ブロックは、 並列領域の始めで複写されます。 その並列領域内で実行するチーム内の各スレッドは、 copyin_entity_list 内のすべてのエンティティーのプライベート・コピーを受け取ります。copyin_entity_list 内に宣言されたすべての変数は、 THREADPRIVATE であるか、 THREADPRIVATE ディレクティブで使用される共通ブロックのメンバーである必要があります。
構文
>>-COPYIN--(--copyin_entity_list--)---------------------------->< |
>>-+-variable_name-----------+--------------------------------->< '-/--common_block_name--/-' |
規則
COPYIN 文節を指定する場合は、以下のことは行えません。
スレッドのチームのマスター・スレッドが COPYIN 文節を含むディレクティブに達すると、 スレッドの変数のプライベート・コピーまたは COPYIN 文節内に指定される共通ブロックは、 マスター・スレッドのコピーと同じ値を持ちます。
COPYIN 文節は、次のディレクティブに適用されます。
目的
COPYPRIVATE 文節を指定する場合は、プライベート変数の値、 またはチーム内の 1 つオブジェクトから共用オブジェクトへのポインターの値は、 そのチーム内の他のすべてのスレッドに対応する変数にコピーされます。 copyprivate_entity_list 内の変数がポインターでない場合は、 そのチーム内のすべてのスレッドの対応する変数は、その変数の値を使用して定義されます。 変数がポインターの場合は、そのチーム内のすべてのスレッドの対応する変数は、 ポインターの関連付け状況を使用して定義されます。 整数ポインターおよび想定サイズ配列は、 copyprivate_entity_list では使用できません。
構文
>>-COPYPRIVATE--(--copyprivate_entity_list--)------------------>< |
>>-+-variable----------------+--------------------------------->< '-/--common_block_name--/-'
規則
共通ブロックが copyprivate_entity_list に含まれる場合は、 THREADPRIVATE ディレクティブ内で指定する必要があります。さらに、 COPYPRIVATE 文節は、object_list 内のすべての変数が copyprivate_entity_list 内に指定されているものとして共通ブロックを扱います。
COPYPRIVATE 文節は、SINGLE 構文の最後にある END SINGLE ディレクティブに指定する必要があります。 コンパイラーは、スレッドがその構文の最後にある暗黙の BARRIER ディレクティブを通過してしまう前に、 COPYPRIVATE 文節を評価します。 copyprivate_entity_list で指定された変数は、 SINGLE 構文の PRIVATE または FIRSTPRIVATE 文節内では使用できません。 END SINGLE ディレクティブが並列領域の動的エクステント内で使用された場合、 copyprivate_entity_list 内に指定した変数は、その並列領域内でプライベートである必要があります。
COPYPRIVATE 文節は、NOWAIT 文節と同じ END SINGLE ディレクティブに指定することはできません。
THREADLOCAL 共通ブロックまたはその共通ブロックのメンバーは、COPYPRIVATE 文節の一部にすることは許されません。
COPYPRIVATE 文節は、次のディレクティブに適用されます。
目的
DEFAULT 文節を指定すると、 並列構文の字句エクステントの中のすべての変数に、 default_scope_attr の有効範囲属性があるように指定することができます。
DEFAULT(NONE) を指定すると、 デフォルトの有効範囲属性は指定されません。 したがって、変数が次のものでない限り、 並列構文のデータ有効範囲属性文節の中の並列構文の 字句エクステントの中で使用するそれぞれの変数を明示的にリストする必要があります。
DEFAULT 文節は、並列構文にある すべての変数が同じ PRIVATE、SHARED のどちらかの 同じデフォルトの有効範囲属性を共用するか、 またはデフォルトの有効範囲属性は使用しないかを指定します。
構文
>>-DEFAULT--(--default_scope_attr--)--------------------------->< |
規則
ディレクティブに DEFAULT(NONE) を指定する場合、 すべての名前付き変数と、FIRSTPRIVATE、LASTPRIVATE、PRIVATE、REDUCTION、 または SHARED 文節にあるディレクティブ構文の 字句エクステント内で参照された配列セクション、配列エレメント、構造体 コンポーネント、またはサブストリングのすべての左端の名前を指定しなければなりません。
ディレクティブに DEFAULT(PRIVATE) を指定する場合、すべての名前付き変数と、ディレクティブ構文の 字句エクステント内で参照された配列セクション、配列エレメント、構文コンポーネント、またはサブストリングの すべての左端の名前は、共通ブロックおよび使用関連付けされた変数を含み (ただし、POINTEE および THREADLOCAL 共通ブロックは除く)、PRIVATE 文節に明示的にリストされているかのように、 スレッドに対して PRIVATE 属性を持ちます。
ディレクティブに DEFAULT(SHARED) を指定する場合、すべての名前付き変数と、ディレクティブ構文の 字句エクステント内で参照された配列セクション、配列エレメント、構文コンポーネント、またはサブストリングの すべての左端の名前は、POINTEE を除き、SHARED 文節に明示的にリストされているかのように、 スレッドに対して SHARED 属性を持ちます。
ディレクティブに DEFAULT 文節を明示的に示さない場合、 デフォルトの動作は、DEFAULT(SHARED) になります。
DEFAULT 文節は、次のディレクティブに適用されます。
例
次の例は、DEFAULT(NONE) の使用法と、 並列領域の中の変数のデータ有効範囲属性を指定するための規則のいくつかを 示しています。
PROGRAM MAIN COMMON /COMBLK/ ABC(10), DEF ! THE LOOP ITERATION VARIABLE, I, IS NOT ! REQUIRED TO BE IN DATA SCOPE ATTRIBUTE CLAUSE !$OMP PARALLEL DEFAULT(NONE) SHARED(ABC) ! DEF IS SPECIFIED ON THE WORK-SHARING DO AND IS NOT ! REQUIRED TO BE SPECIFIED IN A DATA SCOPE ATTRIBUTE ! CLAUSE ON THE PARALLEL REGION. !$OMP DO FIRSTPRIVATE(DEF) DO I=1,10 ABC(I) = DEF END DO !$OMP END PARALLEL END
目的
IF 文節を指定すると、実行時環境は、 ブロックを逐次で実行するのか並列で実行するのかを決定するために、 テストを実行します。 scalar_logical_expression が真である場合、 ブロックは並列で実行され、真でない場合、逐次で実行されます。
構文
>>-IF--(--scalar_logical_expression--)------------------------->< |
規則
PARALLEL SECTIONS 構文の場合、PRIVATE 文節に入っていない変数は、 デフォルトで SHARED として想定されます。
IF 文節は、任意のディレクティブに 1 度だけ組み込めます。
デフォルトでは、ネストされた並列ループは、IF 文節の 設定にかかわりなく逐次化されます。 このデフォルトは、-qsmp=nested_par コンパイラー・オプションを 使用して変更できます。
IF 式は、並列構文のコンテキストの外側で評価されます。 IF 式の中の関数参照は、副次作用を与えるものであってはなりません。
IF 文節は、次のディレクティブに適用されます。
目的
FIRSTPRIVATE 文節を指定する場合は、 それぞれのスレッドは、data_scope_entity_list の中に、 独自の初期化された変数と共通ブロックのローカル・コピーを持っています。
FIRSTPRIVATE 文節は、PRIVATE 文節と同じ変数を指定することができ、 PRIVATE 文節と同様の方法で関数を指定することができます。 例外は、ディレクティブ構文に入る時の変数の状態です。 FIRSTPRIVATE 変数は存在しており、 ディレクティブ構文に入る時にそれぞれのスレッド用に初期化されています。
構文
>>-FIRSTPRIVATE--(--data_scope_entity_list--)------------------>< |
規則
FIRSTPRIVATE 文節の変数は、 以下のいずれにすることもできません。
次の場合、並列構文の FIRSTPRIVATE 文節の中で 変数を指定することはできません。
非同期 I/O 操作を行うエンティティーの 1 つが FIRSTPRIVATE 変数、FIRSTPRIVATE 変数のサブオブジェクト、 または FIRSTPRIVATE 変数に関連付けられたポインターである場合、 一致する暗黙の待機または WAIT ステートメントは、 スレッドが終わる前に実行されなければなりません。
共通ブロックの個々のメンバーがプライベート化されると、 指定された変数のストレージと共通ブロックのストレージとの関連性はなくなります。
FIRSTPRIVATE 変数に関連するストレージである任意の変数は、 並列構文に入るときに未定義になります。
ディレクティブ構文に、非ブロッキング通信を実行する メッセージ送達インターフェース (MPI) ルーチンへの FIRSTPRIVATE 引き数が ある場合、MPI 通信は構文が終わる前に完了する必要があります。
FIRSTPRIVATE 文節は、次のディレクティブに適用されます。
目的
LASTPRIVATE 文節を使用する場合は、 data_scope_entity_list の中にあるそれぞれの変数と共通ブロックは、 PRIVATE であり、 data_scope_entity_list の中のそれぞれの変数の最後の値は、 ディレクティブの構文の外側から参照することができます。 LASTPRIVATE 文節を DO または PARALLEL DO に 使用する場合は、最後の値はループの最後の繰り返しの後の変数の値になります。 LASTPRIVATE 文節を SECTIONS または PARALLEL SECTIONS に 使用する場合は、最後の値は構文の最後の SECTION の後の変数の値になります。 ループの最後の繰り返しまたは構文の最後のセクションで LASTPRIVATE 変数が 定義されない場合、変数はループまたは構文の後でも未定義です。
LASTPRIVATE 文節は、PRIVATE 文節と同様の機能を持っているので、 同じ基準を満たす変数を指定しなければなりません。 ただし、ディレクティブ構文から出る時の変数の状況は例外です。 コンパイラーは、変数の最後の値を決定して、 名前付き変数中に保管されているその値のコピーを取って構文の後に使用します。 LASTPRIVATE 変数は、構文 に入るときに FIRSTPRIVATE 変数でない場合には未定義です。
構文
>>-LASTPRIVATE--(--data_scope_entity_list--)------------------->< |
規則
LASTPRIVATE 文節の変数は、 以下のいずれにすることもできません。
次の場合、並列構文の LASTPRIVATE 文節の中で 変数を指定することはできません。
非同期 I/O 操作を行うエンティティーの 1 つが LASTPRIVATE、LASTPRIVATE 変数のサブオブジェクト、 または LASTPRIVATE 変数に関連付けられたポインターである場合、 一致する暗黙の待機または WAIT ステートメントは、 スレッドが終わる前に実行されなければなりません。
共通ブロックの個々のメンバーがプライベート化されると、 指定された変数のストレージと共通ブロックのストレージとの関連性はなくなります。
LASTPRIVATE 変数に関連するストレージである任意の変数は、 並列構文に入るときに未定義になります。
ディレクティブ構文に、非ブロッキング通信を実行する メッセージ送達インターフェース (MPI) ルーチンへの LASTPRIVATE 引き数が ある場合、MPI 通信はその構文が終わる前に完了する必要があります。
変数を作業共用ディレクティブに LASTPRIVATE として指定し、 そのディレクティブに NOWAIT 文節を指定してある場合は、 その変数を作業共用構文の最後と BARRIER の間に使用することはできません。
並列構文に LASTPRIVATE として指定する変数は、構文 の最後で定義済みになります。 複数のスレッドに同時定義がある場合、 または複数のスレッドで LASTPRIVATE 変数を使用する場合は、 変数が定義済みとなる構文の最後でスレッドが同期化されるようにする必要があります。 たとえば、複数のスレッドが、LASTPRIVATE 変数を持つ PARALLEL 構文を 検出すると、LASTPRIVATE 変数は END PARALLEL で定義済みになるので、 スレッドが END PARALLEL ディレクティブに達するときに、 スレッドを同期化する必要があります。 したがって、PARALLEL 構文全体は、 同期構文内で完結している必要があります。
LASTPRIVATE 文節は、次のディレクティブに適用されます。
例
次の例は、NOWAIT 文節の後で LASTPRIVATE 変数を使用する 正しい方法を示しています。
!$OMP PARALLEL !$OMP DO LASTPRIVATE(K) DO I=1,10 K=I+1 END DO !$OMP END DO NOWAIT ! PRINT *, K **ERROR** ! The reference to K must occur after a ! barrier. !$OMP BARRIER PRINT *, K ! This reference to K is legal. !$OMP END PARALLEL END
目的
NUM_THREADS 文節を使用すると、並列領域で使用するスレッド数を指定できます。 後続の並列領域には反映されません。NUM_THREADS 文節は、omp_set_num_threads ライブラリー・ルーチン または環境変数 OMP_NUM_THREADS を使用して指定されたスレッド数よりも優先されます。
構文
>>-NUM_THREADS--(--scalar_integer_expression--)---------------->< |
規則
scalar_integer_expression の値は正でなければなりません。 式は、 並列領域のコンテキストの外側で評価されます。式の中での 関数呼び出し、および式で参照される変数の値を変更する関数呼び出しの結果は、 どのようになるか予想できません。
動的スレッドを使用可能にするために環境変数 OMP_DYNAMIC を使用する場合は、 scalar_integer_expression は、並列領域で使用可能なスレッドの最大数を定義します。
ネストされた並列領域の一部として NUM_THREADS 文節を 含む場合は、omp_set_nested ライブラリー・ルーチンを指定するか、 または OMP_NESTED 環境変数を設定する必要があります。 そうしない場合は、その並列領域の実行は直列化されます。
NUM_THREADS 文節は、以下の作業共用構造体に適用されます。
目的
作業共用構文に ORDERED 文節を指定すると、並列ループの動的エクステント内に ORDERED ディレクティブを指定できます。
構文
>>-ORDERED----------------------------------------------------->< |
規則
ORDERED 文節は、次のディレクティブに適用されます。
目的
以下にリストされているディレクティブのいずれか 1 つで PRIVATE 文節を指定する場合は、チーム内のそれぞれのスレッドは、 data_scope_entity_list の中に、 独自の未初期化専用変数と共通ブロックのローカル・コピーを持っています。
変数の値が 1 つのスレッドで計算され、 その値が他のスレッドに依存していない場合、または構文 内で使用される前に定義されている場合、 またはその値が構文の終了後には使用されない場合は、 変数には PRIVATE 属性を指定しなければなりません。 PRIVATE 変数のコピーは各スレッドにローカルで存在します。 各スレッドは、PRIVATE 変数の、 初期化されていない独自のコピーを受け取ります。 PRIVATE 変数は、ディレクティブ構文に入る時と出る時に、 未定義の値または関連付け状況を持ちます。 ディレクティブ構文の字句エクステント内にあるすべてのスレッド変数には、 PRIVATE 属性がデフォルトで指定されています。
構文
>>-PRIVATE--(--data_scope_entity_list--)----------------------->< |
規則
PRIVATE 文節の変数には、以下のものを指定することはできません。
次の場合、並列構文の PRIVATE 文節の中で 変数を指定することはできません。
非同期 I/O 操作を行うエンティティーの 1 つが PRIVATE 変数、PRIVATE 変数のサブオブジェクト、 または PRIVATE 変数に関連付けられたポインターである場合、 一致する暗黙の待機または WAIT ステートメントは、 スレッドが終わる前に実行されなければなりません。
共通ブロックの個々のメンバーがプライベート化されると、 指定された変数のストレージと共通ブロックのストレージとの関連性はなくなります。
PRIVATE 変数に関連するストレージである任意の変数は、 並列構文に入るときに未定義になります。
ディレクティブ構文に、非ブロッキング通信を実行する メッセージ送達インターフェース (MPI) ルーチンへの PRIVATE 引き数が ある場合、MPI 通信はその構文が終わる前に完了する必要があります。
PRIVATE 文節の data_scope_entity_list にある変数名は、 割り振り可能オブジェクトであってもかまいません。 このオブジェクトは、ディレクティブ構文に最初に入る時に割り振られていてはなりません。 また、構文を実行するすべてのスレッドのオブジェクトを割り振りおよび割り振り解除しなければなりません。
ディレクティブ構文の動的エクステント内にある 参照されているサブプログラムの SAVE または STATIC 属性 がないローカル変数には、暗黙の PRIVATE 属性があります。
PRIVATE 文節は、次のディレクティブに適用されます。
例
次の例は、ステートメント関数を定義するために使用される PRIVATE 変数の正しい使用法を示しています。コメント行では、無効な使用法が示されています。 ステートメント関数の中に J があるため、J が PRIVATE となっている 並列構文内では、ステートメント関数を参照できません。
INTEGER :: ARR(10), J = 17 ISTFNC() = J !$OMP PARALLEL DO PRIVATE(J) DO I = 1, 10 J=I ARR(I) = J ! ARR(I) = ISTFNC() **ERROR** A reference to ISTFNC would ! make the PRIVATE(J) clause ! invalid. END DO PRINT *, ARR END
目的
REDUCTION 文節は、ディレクティブ構文内にある 文節で宣言された名前付き変数を更新します。 並列構文内では、REDUCTION 変数の 中間値は更新自体以外では使用されません。
構文
>>-REDUCTION--(--+-----------+--variable_name_list--)---------->< '-op_fnc--:-' |
REDUCTION ステートメントの形式は、次のいずれかになります。
>>-reduction_var_ref--=--expr--reduction_op--reduction_var_ref-><
>>-reduction_var_ref--=--reduction_var_ref--reduction_op--expr-><
>>-reduction_var_ref =--reduction_function--(expr,--reduction_var_ref)-><
>>-reduction_var_ref =--reduction_function--(reduction_var_ref,--expr)-><
それぞれの意味は次のとおりです。
それぞれの演算子と組み込み機能の正規の初期化値は、次の表に示されています。
実際の初期化値は、対応する REDUCTION 変数の
データ型と一致します。
組み込み演算子 | 初期化 |
+ | 0 |
* | 1 |
- | 0 |
.AND. | .TRUE. |
.OR. | .FALSE. |
.EQV. | .TRUE. |
.NEQV. | .FALSE. |
.XOR. | .FALSE. |
組み込みプロシージャー | 初期化 |
MAX | 表現できる最小の数 |
MIN | 表現できる最大の数 |
IAND | 全ビットがオン |
IOR | 0 |
IEOR | 0 |
規則
REDUCTION ステートメントには次の規則が適用されます。
共通ブロックの個々のメンバーを REDUCTION 文節に指定すると、 指定された変数のストレージと共通ブロックとの関連性はなくなります。
作業共用構文の REDUCTION 文節の中で指定する変数は、 それを囲んでいる PARALLEL 構文の中で共用される必要があります。
NOWAIT 文節を持つ構文で REDUCTION 文節を使用する場合は、 すべてのスレッドが REDUCTION 文節を完了したことを確認するために バリア同期が実行されるまでは、REDUCTION 変数は未定義のままです。
REDUCTION 変数は、 それが REDUCTION 変数として使用された構文の動的エクステント内で、 別の構文の FIRSTPRIVATE、PRIVATE または LASTPRIVATE 文節の中で使用できません。
REDUCTION 文節に op_fnc が指定されている場合、 variable_name_list の各変数は組み込み型でなければなりません。変数は、ディレクティブ構造の字句エクステント内の REDUCTION ステートメント中でのみ使用できます。op_fnc は、このディレクティブが trigger_constant $OMP を 使用する場合に指定する必要があります。
REDUCTION 文節では縮約演算に入れる名前付き変数を指定します。 コンパイラーは、そのような変数のローカル・コピーを保持しますが、構文 から出るときは各コピーを結合します。 REDUCTION 変数の中間値は、 どのスレッドが計算を最初に終了したかに応じて適当な順序で結合されます。 したがって、ある並列実行と別の並列実行とで ビットが同一の結果になることは保証できません。 これは、複数の並列実行が、同じ数のスレッド、 スケジューリング・タイプ、およびチャンク・サイズを 使用する場合にも当てはまります。
並列構文に REDUCTION または LASTPRIVATE として指定する変数は、 構文の最後で定義済みになります。 複数のスレッドに同時定義がある場合、あるいは複数のスレッドで REDUCTION または LASTPRIVATE 変数を使用する場合は、変数が定義済みとなるときに構文の最後でスレッドが 同期化されるようにする必要があります。 たとえば、複数のスレッドが REDUCTION 変数を持つ PARALLEL 構文を 検出する場合は、REDUCTION 変数は END PARALLEL で定義済みになるので、 スレッドが END PARALLEL ディレクティブに達するときに、 スレッドを同期化する必要があります。 したがって、PARALLEL 構文全体は、 同期構文内で完結している必要があります。
REDUCTION 文節の変数は、組み込み型にしなくてはなりません。 REDUCTION 文節にある変数またはエレメントは、 次のものにすることはできません。
これらの規則は、OpenMP ディレクティブでの REDUCTION の使用法を 説明しています。 REDUCTION 文節を INDEPENDENT ディレクティブで 使用している場合は、INDEPENDENT ディレクティブを参照してください。
OpenMP での REDUCTION 文節は、次のディレクティブに適用されます。
目的
SCHEDULE 文節を使用して、並列化のためのチャンク方式を指定できます。 スケジューリング型またはチャンク・サイズに応じて、 異なる方法で作業がスレッドに割り当てられます。
構文
>>-SCHEDULE--(--sched_type--+----+--)-------------------------->< '-,n-' |
CEILING(number_of_iterations / number_of_threads)
各区画は、最初はスレッドに割り当てられ、n が 指定されている場合は、 その後、さらに n 回の繰り返しを含むチャンクに分割されます。 n が指定されていない場合は、チャンクは次のループ の繰り返しから構成されます。
CEILING(number_of_iterations_remaining_in_partition / 2)
スレッドが解放されると、スレッドが最初に割り当てられた 区画から次のチャンクを取ります。 その区画にチャンクが無くなったら、 スレッドは、最初に別のスレッドを割り当てた区画から次の利用可能なチャンクを取ります。
アクティブなスレッドは、 最初にスリープ・スレッドに割り当てた区分画面の作業を完了させます。
スレッドは、「先入れ先出し」の規則にしたがってこれらのチャンクに 割り当てられます。 残りの作業のチャンクは、利用可能なスレッドに割り当てられます。 この過程はすべての作業が割り当てられるまで続きます。
スリープ状態のスレッドに割り当てられた作業は、 アクティブ・スレッドが利用可能になって時点で、そのスレッドが引き継ぎます。
最初のチャンクのサイズは、次の回数の繰り返しになります。
CEILING(number_of_iterations / number_of_threads)
後続の チャンクは次の繰り返しで構成されます。
CEILING(number_of_iterations_remaining / number_of_threads)
それぞれのスレッドがチャンクを終了する時には、 それぞれのスレッドは、使用可能な次のチャンクを動的に獲得します。
チーム内の複数のスレッドがばらばらに DO 作業共用構文に達し、それぞれの繰り返しにおける 作業量が大体同じであるような状態であれば、ガイド・スケジューリングを使用することができます。 たとえば、DO ループの前に、NOWAIT 文節のある作業共用 SECTIONS または DO 構文が 1 つまたは複数ある場合は、別のスレッドがその最後の繰り返しを実行するのにかかる時間、 または k というチャンク・サイズが指定されている場合は、別のスレッドが最後の k 回の繰り返しを実行するのに かかる時間よりも長くバリアで待つスレッドをなくすことができます。 GUIDED スケジュールでは、すべてのスケジューリング方式の同期化は最も少なくなります。
n 式は、DO 構文のコンテキストの外側で評価されます。 n 式の中の関数参照は、副次作用を与えるものであってはなりません。
SCHEDULE 文節の n パラメーターの値は、チーム内のすべてのスレッドについて同じで なければなりません。
実行時に、スケジューリング・タイプは、環境変数 XLSMPOPTS を使用して指定できます。 その変数を使用してスケジューリング型を指定しない場合、デフォルトのスケジューリング型 STATIC が 使用されます。
n が指定されていない場合、チャンクは次の繰り返しを含みます。
CEILING(number_of_iterations / number_of_threads)
各スレッドは、これらのチャンクのいずれかに割り当てられます。 この方式は、ブロック巡回スケジューリングとして知られています。
スリープ状態のスレッドに作業が割り当てられている場合、 そのスレッドはスリープ状態を解除され、作業を完了します。
ユーザーがコンパイル時または実行時にスケジューリング型を 設定しない場合、STATIC がデフォルトのスケジューリング型 になります。
規則
特定の DO ディレクティブでは、複数の SCHEDULE 文節を指定してはなりません。
SCHEDULE 文節は、次のディレクティブに適用されます。
目的
すべてのセクションは、data_scope_entity_list で 指定されている同じ変数のコピーと共通ブロックを使用します。
SHARED 文節では、 すべてのスレッドから利用できる変数を指定します。 変数を SHARED として指定すると、 ユーザーは、すべてのスレッドにおいて変数の 1 つのコピーを 安全に共用できると宣言したことになります。
構文
>>-SHARED--(--data_scope_entity_list--)------------------------>< |
>>-+-named_variable----------+--------------------------------->< '-/--common_block_name--/-' |
規則
SHARED 文節の変数は、以下のいずれにすることもできません。
SHARED 変数、SHARED 変数の サブオブジェクト、あるいは SHARED 変数と関連付けられた オブジェクト、または SHARED 変数のサブオブジェクトを、 非組み込みプロシージャーを参照するときの実引き数として入れる場合は、 次のようになります。
関連付けられた仮引き数は、明示的形状配列または想定サイズ配列になります。
他のスレッドによって仮引き数と関連付けられた共用ストレージへの参照またはこのストレージの定義は、 プロシージャー参照と同期化される必要があります。 つまり、コードの構造体は、スレッドがプロシージャー参照を検出すると、そのスレッドによるプロシージャー呼び出しと 他のスレッドによる共用ストレージの参照またはこのストレージの定義が常に同じ順序で行われるような構造にしなければ ならないということです。 これは、たとえばプロシージャー参照を BARRIER の後に置くことによって行うことができます。
SHARED 文節は、次のディレクティブに適用されます。
例
次の例では、配列セクション実引き数のあるプロシージャー参照は、 関連した仮引き数は明示的形状配列なので、 プロシージャー参照をクリティカル・セクションに置くことによって、 仮引き数への参照と同期化する必要があります。
INTEGER:: ABC(10) I=2; J=5 !$OMP PARALLEL DEFAULT(NONE), SHARED(ABC,I,J) !$OMP CRITICAL CALL SUB1(ABC(I:J)) ! ACTUAL ARGUMENT IS AN ARRAY ! SECTION; THE PROCEDURE ! REFERENCE MUST BE IN A CRITICAL SECTION. !$OMP END CRITICAL !$OMP END PARALLEL CONTAINS SUBROUTINE SUB1(ARR) INTEGER:: ARR(1:4) DO I=1, 4 ARR(I) = I END DO END SUBROUTINE END
+------------------------------End of IBM 拡張-------------------------------+