Oracle® Solaris Studio 12.4:OpenMP API 用户指南

退出打印视图

更新时间: 2014 年 12 月
 
 

4.5 任务依赖性

OpenMP 4.0 规范介绍了 task 指令中的 depend 子句,该子句会对任务调度强制使用其他约束。这些约束仅在同级任务之间建立依赖关系。同级任务是指属于同一任务区域的子任务的 OpenMP 任务。

当使用 depend 子句指定 in 依赖类型时,生成的任务将是所有以前生成的至少引用了 outinout 依赖类型列表中一个列表项目的同级任务的从属任务。在在 depend 子句中指定了 outinout 依赖类型时,生成的任务将是所有以前生成的至少引用了 inoutinout 依赖类型列表中一个列表项目的同级任务的从属任务。

下面的示例对任务依赖性进行了说明。

示例 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 子句引用相同的变量(abc),任务 5 与任务 1、2、3 或 4 之间也不存在依赖关系。