You can synchronize tasks by using the taskwait or taskgroup directives.
When a thread encounters a taskwait construct, the current task is suspended until all child tasks that it generated before the taskwait region complete execution.
When a thread encounters a taskgroup construct, it commences to execute the taskgroup region. At the end of the taskgroup region, the current task is suspended until all child tasks that it generated in the taskgroup region and all of their descendant tasks complete execution.
Note the difference between taskwait and taskgroup. With taskwait, the current task waits only for its child tasks. With taskgroup, the current task waits not only for the child tasks generated in the taskgroup but also for all the descendants of those child tasks. The following two examples illustrate the difference.
Example 4-5 taskwait Example% 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 }Example 4-6 taskgroup Example
% 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 }
Although the source codes of taskwait.c and taskgroup.c are almost the same, taskwait.c has a taskwait directive at line 23, whereas taskgroup.c has a taskgroup construct at line 10 that contains Task 1 and Task 2. In both programs, the taskwait and taskgroup directives synchronize the execution of Task 1 and Task 3; the difference is in whether they synchronize the execution of Task 2 and Task 3.
In the case of taskwait.c, Task 2 is not a child task of the implicit task generated by the parallel region to which the taskwait region is bound. So, Task 2 does not have to finish by the end of the taskwait region. Task 3 can be scheduled before the completion of Task 2.
In the case of taskgroup.c, Task 2 is a child task of Task 1, which is generated in the taskgroup region. So, Task 2 has to finish by the end of the taskgroup region, before Task 3 is encountered and scheduled.