OpenMP 4.0 规范介绍了 task 指令中的 depend 子句,该子句会对任务调度强制使用其他约束。这些约束仅在同级任务之间建立依赖关系。同级任务是指属于同一任务区域的子任务的 OpenMP 任务。
当使用 depend 子句指定 in 依赖类型时,生成的任务将是所有以前生成的至少引用了 out 或 inout 依赖类型列表中一个列表项目的同级任务的从属任务。在在 depend 子句中指定了 out 或 inout 依赖类型时,生成的任务将是所有以前生成的至少引用了 in、out 或 inout 依赖类型列表中一个列表项目的同级任务的从属任务。
下面的示例对任务依赖性进行了说明。
示例 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
在本例中,任务 1、2、3 和 4 都是同一隐式任务区域的子任务,因此都是同级任务。任务 3 是任务 1 和 2 的从属任务,因为在 depend 子句中的 a 参数指定了依赖性。因此,在任务 1 和 2 完成前,无法调度任务 3。同样,任务 4 是任务 3 的从属任务,因此在任务 3 完成前,无法调度任务 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
在上例中,任务 5 是任务 2 的子任务,不是任务 1、2、3 或 4 的同级任务。因此,尽管 depend 子句引用相同的变量(a、b、c),任务 5 与任务 1、2、3 或 4 之间也不存在依赖关系。