インテル® C++ コンパイラー 15.0 ユーザー・リファレンス・ガイド

omp task

実行が遅延される可能性があるコードブロックの開始位置を指定します。

構文

#pragma omp task [clause[[,]clause]...]

block

引数

clause

次のいずれかです。

final(scalar_expression)

scalar_expression の評価結果が true の場合、生成されるタスクが final タスクになります。

final タスクは、そのすべての派生タスク (子孫) がインクルード・タスクになるよう強制します。

final タスクの実行中に見つかったすべての task 構造は、インクルード・タスクを生成します。

task 構造の final 節の式で変数が使用されると、その task 構造内のすべての構造でその変数が暗黙的に参照されます。

task プラグマでは final 節を 1 つしか指定できません。

private(list)

task 内で private と見なされる変数のリストを指定します。

firstprivate(list)

task 生成時の構文コンテキストにある同じ名前の変数で初期化されるプライベートな変数のリストを指定します。

shared(list)

task 内で参照される構文コンテキストの変数のリストを指定します。

default(shared|none)

default(shared) は、task で使用され、privatefirstprivateshared 節で明示的に宣言されていない変数を共有にします。

default(none) は、task で使用され、privatefirstprivateshared 節で明示的に宣言されていない変数を、コンパイル時に構文エラーとして報告します。

depend

次の 1 つまたは複数の依存タイプを指定できます。また、list には変数および部分配列を指定できます。

  • in(list): 生成されるタスクは、out 節または inout 節の 1 つ以上の list 項目を参照する、以前に生成されたすべての兄弟タスクに依存します。

  • out(list): 生成されるタスクは、in 節、out 節、または inout 節の 1 つ以上の list 項目を参照する、以前に生成されたすべての兄弟タスクに依存します。

  • inout(list): 生成されるタスクは、in 節、out 節、または inout 節の 1 つ以上の list 項目を参照する、以前に生成されたすべての兄弟タスクに依存します。

untied

task の実行を開始したスレッドにタスクをバインドしないように指示します。実行の中断後にチーム内の任意のスレッドでタスク領域を再開できます。例えば、実行時にコンパイラーは、与えられたタスクの実行をスレッド A で開始し、中断した後にスレッド B で再開できます。

if(scalar_expression)

scalar_expression の評価結果が true の場合のみ、囲まれたコード領域を並列に実行するように指示します。 この節を指定しないと、その領域は if(true) を指定した場合と同じように実行されます。

scalar_expression の評価結果が false の場合、到達スレッドは現在の task 領域の実行を直ちに中断し、生成されたタスクの実行を開始しなければなりません。 中断された task 領域は、生成された task が完了するまで再開されません。

この節は、データスコープ属性が有効になる前にマスタースレッドによって評価されます。

task プラグマでは if 節を 1 つしか指定できません。

mergeable

生成されたタスクが undeferred task または included task の場合、代わりに merged task を生成できることを示します。

undeferred task とは、生成される task 領域によって実行が遅延されない task です。つまり、生成される task 領域は undeferred task の実行が完了するまで中断されます。

included task とは、生成される task 領域にシーケンシャルに含められ、実行される task です。つまり、到達スレッドによって直ちに実行されます。

merged task とは、内部制御変数を含むデータ環境が生成される task 領域と同じ task のことです。 内部制御変数 (ICV) については、最新の OpenMP* 仕様を参照してください。

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 タスクが実行されるときに実行できます。


このヘルプトピックについてのフィードバックを送信