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 の検出およびスケジュールを行う必要があります。