OpenMP 4.0 仕様では、task ディレクティブの depend 節を紹介しています。これは、タスクのスケジューリングに対する追加の制約を強制するものです。これらの制約では、兄弟タスク間の依存関係のみを確立します。兄弟タスクとは、同じタスク領域の子タスクである OpenMP タスクです。
in 依存関係タイプを depend 節で指定すると、生成されたタスクは、out または inout 依存関係タイプリスト内の少なくともいずれか 1 つのリスト項目を参照する、以前に生成されたすべての兄弟タスクの従属タスクとなります。out または inout 依存関係タイプを depend 節で指定すると、生成されたタスクは、in、out、または inout 依存関係タイプリスト内の少なくともいずれか 1 つのリスト項目を参照する、以前に生成されたすべての兄弟タスクの従属タスクとなります。
次の例はタスクの依存関係を示しています。
使用例 4-3 兄弟タスクのみを同期化する depend 節の例% cat -n task_depend_01.c
1 #include <omp.h>
2 #include <stdio.h>
3 #include <unistd.h>
4
5 int main()
6 {
7 int a,b,c;
8
9 #pragma omp parallel
10 {
11 #pragma omp master
12 {
13 #pragma omp task depend(out:a)
14 {
15 #pragma omp critical
16 printf ("Task 1\n");
17 }
18
19 #pragma omp task depend(out:b)
20 {
21 #pragma omp critical
22 printf ("Task 2\n");
23 }
24
25 #pragma omp task depend(in:a,b) depend(out:c)
26 {
27 printf ("Task 3\n");
28 }
29
30 #pragma omp task depend(in:c)
31 {
32 printf ("Task 4\n");
33 }
34 }
35 if (omp_get_thread_num () == 1)
36 sleep(1);
37 }
38 return 0;
39 }
% cc -xopenmp -O3 task_depend_01.c
% a.out
Task 2
Task 1
Task 3
Task 4
% a.out
Task 1
Task 2
Task 3
Task 4
この例では、Task 1、2、3、および 4 はすべて同じ暗黙的タスク領域の子タスクであるため、それらは兄弟タスクです。a 引数への依存関係が depend 節に指定されているため、Task 3 は Task 1 と 2 の従属タスクです。したがって、Task 1 と 2 の両方が完了するまで、Task 3 をスケジュールすることはできません。同様に、Task 4 は Task 3 の従属タスクであるため、Task 3 が完了するまで Task 4 をスケジュールすることはできません。
depend 節は兄弟タスクのみを同期化することに注意してください。次の例 (Example 4–4) は、depend 節が兄弟以外のタスクに影響を及ぼさないケースを示しています。
使用例 4-4 兄弟以外のタスクに影響を及ぼさない depend 節の例% cat -n task_depend_02.c
1 #include <omp.h>
2 #include <stdio.h>
3 #include <unistd.h>
4
5 int main()
6 {
7 int a,b,c;
8
9 #pragma omp parallel
10 {
11 #pragma omp master
12 {
13 #pragma omp task depend(out:a)
14 {
15 #pragma omp critical
16 printf ("Task 1\n");
17 }
18
19 #pragma omp task depend(out:b)
20 {
21 #pragma omp critical
22 printf ("Task 2\n");
23
24 #pragma omp task depend(out:a,b,c)
25 {
26 sleep(1);
27 #pragma omp critical
28 printf ("Task 5\n");
29 }
30 }
31
32 #pragma omp task depend(in:a,b) depend(out:c)
33 {
34 printf ("Task 3\n");
35 }
36
37 #pragma omp task depend(in:c)
38 {
39 printf ("Task 4\n");
40 }
41 }
42 if (omp_get_thread_num () == 1)
43 sleep(1);
44 }
45 return 0;
46 }
% cc -xopenmp -O3 task_depend_02.c
% a.out
Task 1
Task 2
Task 3
Task 4
Task 5
上記の例では、Task 5 は Task 2 の子タスクであり、Task 1、2、3、または 4 の兄弟ではありません。このため、depend 節が同じ変数 (a、b、c) を参照しているにもかかわらず、Task 5 と Task 1、2、3、または 4 の間に依存関係はありません。