OpenMP C language API Specification
並列構文
OpenMPの並列構文には、以下の要素がある:
- parallel region 構文:
並列に実行されるparallel region を定義する。
- Work sharing 構文:
parallel region内において、ループなど、現在のteamで分割して実行する。
コメント:
- 入口においては同期は取られない。
- work sharing 構文 と barrier 指示文が実行される場合には、
team 全てのスレッドで実行されなくてはならない。
- work sharing 構文と barrier 指示文は、全てのスレッドで
同じ順序で実行されなくてはならない。
- parallel regionのdynamic extent以外で実行される場合は指定しないの
と同じ(マスタスレッド一つで実行するのと等価)
- 同期構文:
同期を取るための構文
parallel 構文
#pragma omp parallel [ clause ,[[,] clause ] ...]
block-statement
parallel , end parallel は、parallel
regionを定義する。
block-statement 内のコードを複数のスレッドで並列に実行する。
clause は:
- private ( list )
- shared( list )
- defalut(SHARED | NONE)
- firstprivate( list )
- reduction( {operator}: list )
- copyin( list )
- if( scalar_logical_expression )
説明・コメント:
- private, shared, default, firstprivate, reduction, copyinについては
データ環境 を参照。
- IF clauseがあった場合には、条件が真の時のみ並列に実行される。
(偽であった場合には、一つのスレッドで実行される)。
- IF clauseはこの構文のみで使える。
- スレッドに使われる物理プロセッサの数についてはインプリメント依存。
一旦作られたスレッド数は変わらないが、parallel regionごとに違っていて
もよい。 omp_set_dynamic 関数、 OMP_DYNAMIC
環境変数で制御する。
- block-statement では、ブロックの外への飛び出しやブロック内への飛び込みがあっ
てはならない。
動的なextentの中のコードはそれぞれのスレッドで実行されるが、実行のパス
は異なっていてもよい。
- parallel regionの最後において、implicitにバリア同期が取られる。
- もしも、parallel regionを実行中にべつのparallel regionがある場合には、
新しいチームを作り、現在のスレッドがマスタになる。デフォールトでは、
nestされたparallel regionは逐次に実行される。すなわち、1つのスレッド
で構成されたチームで実行される。これは、 omp_set_nested
関数、 OMP_NESTED 環境変数で制御できる。
- 中のコードはstructured blockでなくてはならない。飛び出し、飛び込みは不
可。
for 構文
#pragma omp for [ clause , ...]
for(...; ...; ...) body
並列に実行されるループを指定する。
parallel region内の場合、直後のforループを並列に実行する。
この構文で指定可能な clause は、
- private( list )
- firstprivate( list )
- lastprivate( list )
- reduction(op: list)
- schedule(type[,chunk])
- ordered
- nowait
また、 parallel 構文内に一つの並列ループのみがある場合には、次
の省略形を用いることができる。
#pragma omp parallel for [ clause , ...]
for(...; ...; ...) body
この構文ではifを除く、parallelで指定できるclauseが全て指定可能となる。
forループは、canonical loopで無くてはならない。canonicalとは、
scheduleは、ループをどのようにスレッドに分割して実行するか
を指定する。
-
schedule(static[,chunk])
-
chunkで指定されたサイズを単位として、各スレッドにround-robin方式で
iterationを割り当てる。
chunkが指定されていない場合には等分割。
-
schedule(dynamic[,chunk])
-
指定されたchunkサイズのiterationをスレッドに割り当てて並列実行し、担当
したchunkの実行が終了したスレッドが残りのiterationから再びchunkサイズ
を割り当てて実行していく。
chunkが指定されていない場合には1。
-
schedule(guided[,chunk])
-
指定されたchunkを最初の割り当て単位として、Guided Self Schedulingを用
いてiterationの割り当てを実行時に行う。
割り当てサイズは、残りのiterationに対応してexponentialに減らしていく。
chunkが指定されていない時には1。
-
schedule(runtime)
-
実行時に決定する。OMP_SCHEDULE環境変数で設定する。指定されていない場合
には、インプリメント依存。
chunkの指定はなし(エラー)。
-
scheduleの指定がない場合には、インプリメント依存。
-
OpenMP-compliantなプログラムはループの実行順序によらずに正しく実
行できなくてはならない。すなわち、上記のスケジューリングを指定したとし
ても、コンパイラによってバリエーションがあるため、上記の特定のスケジュー
リングに依存するべきではない。
説明・コメント:
private, firstprivate, lastprivate, reduction については、
データ環境 を参照。
- ordered 構文が動的なextentに現れる時には、orderedを指定しておかなく
てはならない。
-
nowaitが指定されている時には、implicitにbarrier同期が取られる。
nowaitが指定されている場合には、最後に同期を取らない。
-
ループの外側に飛び出すことは不可。
-
schedule, orderedは for 構文のみ。
sections 構文
#pragma omp sections [ clause ....]
{
[#pramga omp section]
block-statement
[#pramga omp section
block-statement
]
....
}
それぞれのセクションを並列に実行する。それぞれのセクションは一度だけ実
行される。
この構文で指定可能な clause は
- private(list)
- firstprivate(list)
- lastprivate(list)
- reduction(...)
- nowait
また、 parallel 構文内に一つのセクション構文のみがある場合には、
次の省略形を用いることができる。
#pragma omp parallel sections [ clause ....]
{
[#pramga omp section]
block-statement
[#pramga omp section
block-statement
]
....
}
この構文では、sectionsとparallelで指定できるclauseが全て指定可能である。
説明・コメント:
-
section 構文は、 sections/end sections
のlexical extent内になくてはならない。
-
nowait が指定されていない場合には、 end sections
でバリアを取る。
-
blockの中からの飛び出し、飛び込みは不可。
-
lastprivate が指定されているときには、この部分を逐次実行した場合に
得られる値を反映する。
-
sectionの数がteamのスレッド数よりも小さい場合には、いくつかの部分は逐
次実行される。
single 構文
#pragma omp single [ clause ...]
block-statement
一つのスレッドだけで実行される部分を定義する。
clause は
- private( list )
- firstprivate( list )
- nowait
説明・コメント:
- nowaitが指定されていない場合には、他のスレッドは待つ(バリア同期を
行う)。
- blockの中からの飛び出し、飛び込みは不可。
master 構文
#pragma omp master
block-statement
マスタスレッドのみが実行する部分を定義する。
説明・コメント:
- 同期は取られない。
- blockからの飛び出し、飛び込みは不可
critical 構文
#pragma omp critical [( name )]
block-statement
nameで指定されるcritical sectionを定義する。
説明・コメント:
- 名前なしの場合は、他の名前なしのcritical sectionと同じcritical
sectionを構成する。
- critical sectionの名前は、globalなentityである。すなわち、異なる
ファイル間であっても、同じ名前のcritical sectionは排他制御される。
barrier 指示文
#pragma omp barrier
チーム内のスレッド間でのバリア同期を行う。
atomic 構文
#pragma omp atomic
statement
次の文をアトミックに実行する。あるメモリの内容がatomicに更新されること
を保証する。次の文だけに有効。次の文は以下のものでなくてはならない。
- x binop = expr
- x++
- ++x
- x--
- --x
xはスカラー型のlvalue式でなくてはならない。exprはスカラ型の値の式で、x
を含んではならない。binopは、 +,*,-,/,&,^,|,<<,>>
のいずれ
か。
説明・コメント:
-
xのload/storeのみがatomicで、exprの評価自体はatomicでなくてもよい。
-
全てのxのアドレスに対するreferenceは、同じタイプでなくてはならない。
- atomicの更新をサポートするハードウエアがある場合には高速に実行で
きる。
-
MAX,MINについてはどうするのか?
critical sectionで代用ができる?
flush 指示文
#pragma omp flush [(list)]
この時点で、list内に指定されている変数について、
メモリの一貫性を保証する。リストがない場合には全ての変数に関してのメモ
リの一貫性を保証する。
thread-visibleな変数は、メモリに対して書き戻される。例えば、コンパイラ
はレジスタ上の値をメモリに書き戻し、ハードウエアはwrite bufferをフラッ
シュする。
flush 指示文は以下の構文で、暗黙の内に実行される。
- barrier
- criticalの最後
- orderedの最後
- parallelの最後
- forの最後
- sectionsの最後
- singleの最後
もしも、nowaitが指定されていれば、実行されない。
volatileな変数への書き込みはflushと同じような効果をもつ。
ordered 構文
#pragma omp ordered
block-statement
#pragma omp end ordered
blockを逐次loopと同じ順序で実行することを指定する。
ordered 構文は parallel ループの動的なextentにのみ
現れることができる。このparallelループでは、orderedが指定されてい
なくてはならない。orderedで指定されるblockは、一度に一つのスレッドでし
か実行されない。スレッドはそれまでのiterationの実行が終らない限り、こ
のblockを実行しない。この構文は、このblock以外の部分は並列に実行
できることを示す。
directive bindingについての規則
- for, sections, single, master, barrierの各directiveは、それを含む
parallel regionに、動的にbindingされる。
- ordered directiveは、それを含むfor directiveに動的にbindされる。
- atomic directiveは、teamのスレッド間だけでなく、全てのスレッド間
で排他アクセスを保証する。
- critical directiveは、同じ名前に対して、teamのスレッド間だけでな
く、全てのスレッド間で排他アクセスを保証する。
- directiveは、parallel regionの外では、どのdirectiveともbindしない。
directive nestについての規則
- parallel directiveがnestしている場合には、nested parallelismが
enableにならない限り、内側のparallel regionは、現在のスレッドからなる
1つのスレッドのteamで実行される。
- 同じparallel regionにバインドされている for, sections, single
directiveは、ネストしてはならない。
- for, sections, single directiveは、critical, master directiveの
dynamic extentに使ってはならない。
- barrier directiveは、for, sections, master, critical directiveの
dynamic extentにつかってはならない。
- master directiveは for, section, single directiveのdynamic extent
に現れてはならない。
- ordered directiveは、cirtical directiveのdynamic extentに現れては
ならない。
- parallel region内で動的に正しく実行されるdirectiveは、parallel
regionの外で実行されても正しい。外側で実行される場合には、あたかもマス
タスレッド1つからなるteamで実行されるように振舞う。