インテル® C++ コンパイラー 16.0 ユーザー・リファレンス・ガイド
実行が遅延される可能性があるコードブロックの開始位置を指定します。
#pragma omp task [clause[[,]clause]...] |
block
スレッドが task 構造に到達すると、関連付けられた構造化ブロックのコードに対する task が生成されます。到達スレッドは、直ちにタスクを実行するか、または実行を保留します。実行が保留された場合、タスクはチーム内の任意のスレッドに割り当てられます。
タスク領域内のタスク・スケジュール・ポイントに到達したスレッドは、そのタスク領域を一時的に中断することがあります。その場合、デフォルトではタスクがバインドされ、中断されたタスク領域はそれを開始したスレッドによってのみ再開できます。ただし、task 構造で untied 節が指定されている場合は、中断後にチーム内の任意のスレッドでそのタスク領域を再開できます。次の場合には、untied 節は無視されます。
task 構造は、外側のタスクの中に入れ子されることがありますが、内側タスクのタスク領域は、外側タスクのタスク領域の一部ではありません。
task 構造には、生成されるタスクのタスク領域に (明示的なタスクの生成直後に) タスク・スケジュール・ポイントがあります。そして、それぞれの明示的なタスク領域には、その終了ポイントにタスク・スケジュール・ポイントがあります。タスク・スケジュール・ポイントは、untied タスク領域の任意の場所に追加することができます。
明示的なタスク領域によって記憶域が共有される場合は、その実行が完了する前に記憶域が無効にならないように、適切な同期を追加する必要があります。
プログラムは、task プラグマの節の評価の順序や影響に依存してはなりません。タスク領域の内側から外側へ、または外側から内側へ分岐するプログラムはサポートされません。
同じユニットの複数のタスクで、同期せずに C++ I/O 文を使用した場合の動作は不定です。
例 |
---|
struct node { struct node *left; struct node *right; }; extern void process(struct node *); int depth, limit; void traverse( struct node *p ) { // depth > limit になったら、新しいタスクの生成を停止し、 // コンパイラーが新しいデータ環境を生成しないようにします。 if (p->left) #pragma omp task final(depth>limit) mergeable // p はデフォルトで firstprivate traverse(p->left); if (p->right) #pragma omp task final(depth>limit) mergeable // p はデフォルトで firstprivate traverse(p->right); process(p); } |
依存性があるタスクを作成する例 |
---|
int a; #pragma omp task depend(out:a) {} #pragma omp task depend(in:a) {} #pragma omp task depend(in:a) {} #pragma omp task depend(out:a) {} |
上記の簡単な例は、依存性がある 4 つのタスクを作成します。1 つ目のタスクはどのタスクにも依存しません。2 つ目と 3 つ目のタスクは 1 つ目のタスクには依存しますが、互いには依存しません。最後のタスクは 2 つ目と 3 つ目のタスクに依存します。
依存性がある兄弟タスクの例 |
---|
int a[N*B]; for (int I=0; I< N; I++ ) #pragma omp task depend(output:a[i*B:B]) Fill(&a[i*B]); for (int I = 0; I <–1; I++ ) #pragma omp task depend(inout:a[i*B:B]) depend(in:a[(i+1)*B:B]) Process(&a[i*B],&a[(I+1)*B]); for (int I = 0; I <N; I++ ) #pragma omp task depend(in:a[i*B:B]) Output(&a[i*B]); |
1 つ目のループのタスクは、依存する以前のタスクが同じ list 項目に存在しないため、互いに独立しています。2 つ目のループのタスクは、1 つ目のループの 2 つのタスク (I*B を参照するタスクと (I+1)*B を参照するタスク) に依存します。
依存関係はシーケンシャルに構築されるため、in 依存性はループのタスクが以前の反復のタスクに依存するように強制します。最後に、3 つ目のループのタスクは、2 つ目のループの対応する Process タスクが実行されるときに実行できます。