Oracle® Solaris Studio 12.4: OpenMP API User's Guide

Exit Print View

Updated: December 2014
 
 

4.5 Task Dependence

The OpenMP 4.0 specification introduces the depend clause on the task directive, which enforces additional constraints on the scheduling of tasks. These constraints establish dependences between sibling tasks only. Sibling tasks are OpenMP tasks that are child tasks of the same task region.

When the in dependence-type is specified with the depend clause, the generated task will be a dependent task of all previously generated sibling tasks that reference at least one of the list items in an out or inout dependence-type list. When the out or inout dependence-type is specified on the depend clause, the generated task will be a dependent task of all previously generated sibling tasks that reference at least one of the list items in an in, out, or inout dependence-type list.

The following example illustrates task dependence.

Example 4-3  Illustrating the depend Clause Synchronizing Only Sibling Tasks
% 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

In this example, Tasks 1, 2, 3, and 4 are all child tasks of the same implicit task region, and so are sibling tasks. Task 3 is a dependent task of Tasks 1 and 2 because of the dependences on the a argument specified in the depend clauses. Therefore, Task 3 cannot be scheduled until both Tasks 1 and 2 have completed. Similarly, Task 4 is a dependent task of task 3 so Task 4 cannot be scheduled until Task 3 has completed.

Note that the depend clause synchronizes sibling tasks only. The following example (Example 4–4) shows a case where the depend clause does not affect non-sibling tasks.

Example 4-4  Illustrating the depend Clause Not Affecting non-Sibling Tasks
% 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

In this above example, Task 5 is a child task of Task 2 and is not a sibling of Tasks 1, 2, 3 or 4. So, despite the depend clauses referencing the same variables (a, b, c), there is no dependence between Task 5 and Tasks 1, 2, 3, or 4.