您可以使用 taskwait 或 taskgroup 指令同步任务。
当线程遇到 taskwait 构造时,当前任务会暂停,直到它在 taskwait 区域前生成的所有子任务均已完成执行为止。
当线程遇到 taskgroup 构造时,它将开始执行 taskgroup 区域。在 taskgroup 区域末尾,当前任务暂停,直到它在 taskgroup 区域中生成的所有子任务及其所有子孙任务均已完成执行为止。
请注意 taskwait 与 taskgroup 之间的不同。使用 taskwait,当前任务仅等待其子任务。使用 taskgroup,当前任务不仅等待在 taskgroup 中生成的子任务,还等待这些子任务的所有子孙任务。下面两个示例介绍了二者之间的差异。
示例 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 行有包含任务 1 和任务 2 的 taskgroup 构造。在这两个程序中,taskwait 和 taskgroup 指令同步任务 1 和任务 3 的执行;不同之处在于它们是否同步任务 2 和任务 3 的执行。
在使用 taskwait.c 的情况下,任务 2 不是 taskwait 区域绑定到的并行区域所生成的隐式任务的子任务。因此,任务 2 不必在 taskwait 区域末尾完成。可以在完成任务 2 之前调度任务 3。
对于 taskgroup.c,任务 2 是任务 1 的子任务,该任务是在 taskgroup 区域中生成的。因此,任务 2 必须在 taskgroup 区域末尾完成,然后才能遇到和调度任务 3。