次の方法で共有


2.4.1 for のコンストラクト

for ディレクティブは、関連付けられているループの反復処理を並列実行するように指定する反復の work-sharing コンストラクトを識別します。for ループの反復処理は、バインドされた並列コンストラクトを実行するチームに存在しているスレッド間で分散されます。for コンストラクトの構文は次のとおりです。

#pragma omp for [clause[[,] clause] ... ] new-line
   for-loop

clause は次のいずれかになります。

private(variable-list)

firstprivate(variable-list)

lastprivate(variable-list)

reduction(operator : variable-list)

ordered

schedule(kind[, chunk_size])

nowait

for ディレクティブにより、対応する for ループ構造に制限が設定されます。対応する for ループは次の正規形である必要があります。

for (init-expr; var logical-op b; incr-expr**)**

  • init-expr
    次のいずれか。

    var = lb

    integer-type var = lb

  • incr-expr
    次のいずれか。

    ++var

    var ++

    -- var

    var --

    var += incr

    var -= incr

    var = var + incr

    var = incr + var

    var = var - incr

  • var
    符号付き整数変数。この変数が共有になっている場合でも、for の存続期間中、これは暗黙的にプライベートになります。この変数は、for ステートメントの本体内で変更できません。変数が lastprivate に指定されていない限り、ループ後の値は未定義です。

  • logical-op
    次のいずれか。

    <

    <=

    >

    >=

  • lbb、および incr
    ループ インバリアント整数式。これらの式の評価中に同期は起こりません。したがって、評価中の副作用は不定の結果になります。

正規形では、ループの入り口でループの反復処理回数が計算されます。この計算は、整数の上位変換後、var 型の値で実行されます。特に、b - lb + incr の値がその型で表せない場合は、結果は不定になります。さらに、logical-op が < または <= の場合、incr-exprvar がループの各反復で増加していく式になります。logical-op が > または >= の場合、incr-exprvar がループの各反復で減少していく式になります。

schedule 句は、for ループの反復処理がチームのスレッド間で分散される方法を指定します。特定の反復を実行するスレッドによってプログラムの動作に影響が出ないようにする必要があります。chunk_size の値が指定されている場合、これは正の値のループ インバリアント整数式である必要があります。この式の評価中に同期は起こりません。したがって、評価中の副作用は不定の結果になります。schedule kind は以下のいずれかです。

表 2-1 schedule 句の kind の値

static

schedule(static, chunk_size) が指定されている場合、反復処理は chunk_size で指定されているサイズのチャンクで分割されます。チャンクは、チーム内のスレッドに、スレッド番号順にラウンド ロビン方式で静的に割り当てられます。chunk_size が指定されている場合、反復領域は、サイズがほぼ同じチャンクに分割され、各チャンクが各スレッドに割り当てられます。

dynamic

schedule(dynamic, chunk_size) が指定されている場合、反復処理は、chunk_size のチャンクに分割されます。各チャンクが、割り当てを待機しているスレッドに割り当てられます。スレッドは、反復処理のチャンクを実行し、その後、次の割り当てを待機します。これは、割り当てられるチャンクがなくなるまで続きます。最後に割り当てられるチャンクは他のチャンクより反復処理数が少なくなる場合があります。chunk_size が指定されていない場合、既定値は 1 です。

guided

schedule(guided, chunk_size) が指定されている場合、反復処理のチャンクが徐々に小さくなりながらスレッドに割り当てられます。スレッドに割り当てられたチャンクの処理が終了すると、残りのチャンクがなくなるまで、動的に別のチャンクにスレッドが割り当てられます。chunk_size が 1 の場合、残りの反復処理をスレッド数で割ったおおよその値が各チャンクのサイズになります。チャンク サイズは 1 に向かって指数的に小さくなります。chunk_size に 1 より大きい k を指定した場合、チャンク サイズは指数的に k まで小さくなります。ただし、最後のチャンクは k より小さくなる場合があります。chunk_size が指定されていない場合、既定値は 1 です。

runtime

schedule(runtime) が指定されている場合、スケジュール方法は実行時に決定されます。スケジュールの kind やチャンク サイズは、環境変数 OMP_SCHEDULE を設定することにより、実行時に選択されます。この環境変数が設定されていない場合、選択されるスケジュールは実装で定義されます。schedule(runtime) を指定した場合、chunk_size は指定できません。

schedule 句が明示的に指定されなかった場合、既定の schedule は実装で定義されます。

OpenMP 対応のプログラムの動作を、特定のスケジュールに依存させないでください。同じスケジュール kind でもコンパイラごとに異なる実装がなされる可能性があるため、プログラムの動作を、上記の説明に厳密に準拠するスケジュールの kind に依存させないでください。これらの説明は、特定の状況に合ったスケジュール方法を選択する場合に使用できます。

ordered ディレクティブが for コンストラクトにバインドされる場合、ordered 句が存在している必要があります。

nowait 句が指定されていない限り、for コンストラクトの末尾に暗黙のバリアがあります。

for ディレクティブに対する制限は次のとおりです。

  • for ループは構造化ブロックである必要があります。また、break ステートメントでループの実行を終了できません。

  • for ディレクティブに関連付けられている for ループのループ制御式の値は、チーム内のすべてのスレッドで同じである必要があります。

  • for ループの反復処理変数は、符号付き整数型である必要があります。

  • for ディレクティブに指定できる schedule 句は 1 つだけです。

  • for ディレクティブに指定できる ordered 句は 1 つだけです。

  • for ディレクティブに指定できる nowait 句は 1 つだけです。

  • chunk_sizelbb、または incr の式内に副作用が発生するかどうか、またはその回数は未定義です。

  • chunk_size 式の値は、チーム内のすべてのスレッドに対して同じである必要があります。

クロス リファレンス

  • privatefirstprivatelastprivatereduction の各句については、25 ページの「2.7.2 データ共有属性句」を参照してください。

  • OMP_SCHEDULE 環境変数については、48 ページの「4.1 OMP_SCHEDULE」を参照してください。

  • ordered コンストラクトについては、22 ページの「2.6.6 ordered コンストラクト」を参照してください。

  • schedule 句の使用の詳細については、93 ページの「D. schedule 句の使用」を参照してください。