taskwait または taskgroup ディレクティブを使用してタスクを同期化できます。
スレッドが taskwait 構文を検出すると、現在のタスクは、それが taskwait 領域の前に生成したすべての子タスクの実行が完了するまで中断されます。
スレッドが taskgroup 構文を検出すると、taskgroup 領域の実行が開始されます。taskgroup 領域の終わりで、現在のタスクは、taskgroup 領域でそのタスクが生成したすべての子タスクとそのすべての子孫タスクの実行が完了するまで中断されます。
taskwait と taskgroup の違いに注意してください。taskwait を使用すると、現在のタスクはその子タスクのみを待機します。taskgroup を使用すると、現在のタスクは、taskgroup 領域で生成された子タスクだけでなく、その子タスクのすべての子孫も待機します。次の 2 つの例は、その違いを示しています。
使用例 4-5 taskwait の例% cat -n taskwait.c 1 #include <omp.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 5 int main() 6 { 7 #pragma omp parallel 8 #pragma omp single 9 { 10 #pragma omp task 11 { 12 #pragma omp critical 13 printf ("Task 1\n"); 14 15 #pragma omp task 16 { 17 sleep(1); 18 #pragma omp critical 19 printf ("Task 2\n"); 20 } 21 } 22 23 #pragma omp taskwait 24 25 #pragma omp task 26 { 27 #pragma omp critical 28 printf ("Task 3\n"); 29 } 30 } 31 32 return 0; 33 }使用例 4-6 taskgroup の例
% cat -n taskgroup.c 1 #include <omp.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 5 int main() 6 { 7 #pragma omp parallel 8 #pragma omp single 9 { 10 #pragma omp taskgroup 11 { 12 #pragma omp task 13 { 14 #pragma omp critical 15 printf ("Task 1\n"); 16 17 #pragma omp task 18 { 19 sleep(1); 20 #pragma omp critical 21 printf ("Task 2\n"); 22 } 23 } 24 } /* end taskgroup */ 25 26 #pragma omp task 27 { 28 #pragma omp critical 29 printf ("Task 3\n"); 30 } 31 } 32 33 return 0; 34 }
taskwait.c と taskgroup.c のソースコードはほとんど同じですが、taskwait.c の 23 行目に taskwait ディレクティブがあるのに対し、taskgroup.c の 10 行目には Task 1 と Task 2 を含む taskgroup 構文があります。どちらのプログラムでも、taskwait および taskgroup ディレクティブは Task 1 と Task 3 の実行を同期化しています。両者の違いは、それらが Task 2 と Task 3 の実行を同期化しているかどうかにあります。
taskwait.c の場合、Task 2 は、taskwait 領域がバインドされている並列領域によって生成される暗黙的タスクの子タスクではありません。そのため、taskwait 領域の終わりまでに Task 2 を終了させる必要はありません。Task 3 は Task 2 の完了前にスケジュールできます。
taskgroup.c の場合、Task 2 は、taskgroup 領域で生成される Task 1 の子タスクです。そのため、taskgroup 領域の終わりまでに Task 2 を終了させてから、Task 3 の検出およびスケジュールを行う必要があります。