JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris Studio 12.3:OpenMP API 用户指南     Oracle Solaris Studio 12.3 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  OpenMP API 简介

2.  编译并运行 OpenMP 程序

3.  实现定义的行为

4.  嵌套并行操作

5.  任务处理

6.  自动确定变量的作用域

6.1 自动确定作用域数据范围子句

6.1.1 __auto 子句

6.1.2 default(__auto) 子句

6.2 并行构造的作用域规则

6.2.1 标量变量的作用域规则

6.2.2 数组的作用域规则

6.3 任务构造的作用域规则

6.3.1 标量变量的作用域规则

6.3.2 数组的作用域规则

6.4 关于自动确定作用域的通用注释

6.5 限制

6.6 检查自动确定作用域的结果

6.7 自动确定作用域示例

7.  作用域检查

8.  性能注意事项

A.  子句在指令中的放置

索引

6.7 自动确定作用域示例

本节提供了一些示例来说明自动确定作用域规则的工作原理。

示例 6-4 更复杂的示例

 1.      REAL FUNCTION FOO (N, X, Y)
 2.      INTEGER       N, I
 3.      REAL          X(*), Y(*)
 4.      REAL          W, MM, M
 5.
 6.      W = 0.0
 7.
 8. C$OMP PARALLEL DEFAULT(__AUTO)
 9.
10. C$OMP SINGLE
11.       M = 0.0
12. C$OMP END SINGLE
13.
14.       MM = 0.0
15.
16. C$OMP DO
17.       DO I = 1, N
18.          T = X(I)
19.          Y(I) = T
20.          IF (MM .GT. T) THEN
21.             W = W + T
22.             MM = T
23.          END IF
24.       END DO
25. C$OMP END DO
26.
27. C$OMP CRITICAL
28.       IF ( MM .GT. M ) THEN
29.          M = MM
30.       END IF
31. C$OMP END CRITICAL
32.
33. C$OMP END PARALLEL
34.
35.      FOO = W - M
36.
37.      RETURN
38.      END

函数 FOO() 包含一个并行区域,该并行区域包含一个 SINGLE 构造、一个工作共享 DO 构造和一个 CRITICAL 构造。除 OpenMP 并行构造外,并行区域中的代码还执行以下操作:

  1. 将数组 X 中的值复制到数组 Y

  2. 查找 X 中的最大正数值,并将其存储在 M

  3. X 的一些元素的值累加到变量 W 中。

编译器如何使用这些规则正确地确定并行区域中变量的作用域?

在并行区域中使用下列变量:INMMTWMXY。编译器将确定以下信息:

示例 6-5 使用 QuickSort 的示例

static void par_quick_sort (int p, int r, float *data)
{
   if (p < r) 
   {
      int q = partition (p, r, data);  
      
      #pragma omp task default(__auto) if ((r-p)>=low_limit)
      par_quick_sort (p, q-1, data);

      #pragma omp task default(__auto) if ((r-p)>=low_limit)
      par_quick_sort (q+1, r, data);
   }
}

int main ()
{
  ...
  #pragma omp parallel
  {
     #pragma omp single nowait
     par_quick_sort (0, N-1, &Data[0]);
  }
  ...
}

er_src result:

      Source OpenMP region below has tag R1
      Variables autoscoped as FIRSTPRIVATE in R1: p, q, data
      Firstprivate variables in R1: data, p, q
        47. #pragma omp task default(__auto) if ((r-p)>=low_limit)
        48. par_quick_sort (p, q-1, data);
      
      Source OpenMP region below has tag R2
      Variables autoscoped as FIRSTPRIVATE in R2: q, r, data
      Firstprivate variables in R2: data, q, r
        49. #pragma omp task default(__auto) if ((r-p)>=low_limit)
        50. par_quick_sort (q+1, r, data);

标量变量 pq 以及指针变量数据在任务构造和并行区域中都是只读的。因此,根据 TS1 自动将其作用域确定为 FIRSTPRIVATE

示例 6-6 另一个 Fibbonacci 示例

int fib (int n)
{
   int x, y;
   if (n < 2) return n;

   #pragma omp task default(__auto)
   x = fib(n - 1);

   #pragma omp task default(__auto)
   y = fib(n - 2);

   #pragma omp taskwait
   return x + y;
}

er_src result:

   Source OpenMP region below has tag R1
   Variables autoscoped as SHARED in R1: x
   Variables autoscoped as FIRSTPRIVATE in R1: n
   Shared variables in R1: x
   Firstprivate variables in R1: n
    24.         #pragma omp task default(__auto) /* shared(x) firstprivate(n) */
    25.         x = fib(n - 1);
   
   Source OpenMP region below has tag R2
   Variables autoscoped as SHARED in R2: y
   Variables autoscoped as FIRSTPRIVATE in R2: n
   Shared variables in R2: y
   Firstprivate variables in R2: n
    26.         #pragma omp task default(__auto) /* shared(y) firstprivate(n) */
    27.         y = fib(n - 2);
    28. 
    29.         #pragma omp taskwait
    30.         return x + y;
    31. }

标量 n 在任务构造和并行构造中都是只读的。因此,根据 TS1 自动将 n 的作用域确定为 FIRSTPRIVATE

标量变量 xy 是函数 fib() 的局部变量。在两个任务中访问 xy 不会导致数据争用。由于存在一个 taskwait,因此这两个任务将在执行 fib() 的线程(遇到了这两个任务)退出 fib() 之前完成执行。这意味着 xy 将在这两个任务执行时处于活动状态。因此,根据 TS2 自动将 xy 的作用域确定为 SHARED

示例 6-7 另一个自动确定作用域示例

int main(void)
{
  int yy = 0;

  #pragma omp parallel default(__auto) shared(yy)
  {
    int xx = 0;

    #pragma omp single
    {
       #pragma omp task default(__auto) // task1
       {
          xx = 20;
       }
    }

    #pragma omp task default(__auto) // task2
    {
       yy = xx;
    }
  }

  return 0;
}

er_src result:

   Source OpenMP region below has tag R1
   Variables autoscoped as PRIVATE in R1: xx
   Private variables in R1: xx
   Shared variables in R1: yy
     7.   #pragma omp parallel default(__auto) shared(yy)
     8.   {
     9.     int xx = 0;
    10.

   Source OpenMP region below has tag R2
    11.     #pragma omp single
    12.     {

   Source OpenMP region below has tag R3
   Variables autoscoped as SHARED in R3: xx
   Shared variables in R3: xx
    13.        #pragma omp task default(__auto) // task1
    14.        {
    15.           xx = 20;
    16.        }
    17.     }
    18.

   Source OpenMP region below has tag R4
   Variables autoscoped as PRIVATE in R4: yy
   Variables autoscoped as FIRSTPRIVATE in R4: xx
   Private variables in R4: yy
   Firstprivate variables in R4: xx
    19.     #pragma omp task default(__auto) // task2
    20.     {
    21.        yy = xx;
    22.     }
    23.   }

在此示例中,xx 是并行区域中的专用变量。组中的其中一个线程会修改 xx 的初始值(通过执行 task1)。然后,所有线程都会遇到使用 xx 执行某些计算的 task2

task1 中,使用 xx 不会导致数据争用。由于单个构造结尾有一个隐式屏障,而且 task1 应在退出此屏障之前完成,因此,xx 将在 task1 执行时处于活动状态。所以,根据 TS2,在 task1 中自动将 xx 的作用域确定为 SHARED

task2 中,xx 的使用是只读的。但是,xx 的使用在包含它的并行构造中不是只读的。由于 xx 在并行构造中预先确定为 PRIVATE,因此无法确定 xx 是否将在执行 task2 时处于活动状态。所以,根据 TS3,在 task2 中自动将 xx 的作用域确定为 FIRSTPRIVATE

task2 中,使用 yy 会导致数据争用,在每个执行 task2 的线程中,在读取变量 yy 之前始终先由同一线程写入该变量。所以,根据 TS4,在 task2 中自动将 yy 的作用域确定为 PRIVATE

示例 6-8 最后一个示例

int foo(void)
{
  int xx = 1, yy = 0;

  #pragma omp parallel shared(xx,yy)
  {
    #pragma omp task default(__auto)
    {
       xx += 1;

       #pragma omp atomic
       yy += xx;
    }

    #pragma omp taskwait
  }
  return 0;
}

er_src result:

   Source OpenMP region below has tag R1
   Shared variables in R1: yy, xx
     5.   #pragma omp parallel shared(xx,yy)
     6.   {

   Source OpenMP region below has tag R2
   Variables autoscoped as SHARED in R2: yy
   Variables autoscoped as FIRSTPRIVATE in R2: xx
   Shared variables in R2: yy
   Firstprivate variables in R2: xx
     7.     #pragma omp task default(__auto)
     8.     {
     9.        xx += 1;
    10.
    11.        #pragma omp atomic
    12.        yy += xx;
    13.     }
    14.
    15.     #pragma omp taskwait
    16.   }

task 构造中,xx 的使用不是只读的,且会导致数据争用。但在任务区域中读取 x 会获取在任务之外定义的 x 值。(在此示例中,由于 xx 对于并行区域确定为 SHARED,因此 x 的定义实际上在并行区域之外。)所以,根据 TS5,自动将 xx 的作用域确定为 FIRSTPRIVATE

task 构造中,yy 的使用不是只读的,但不会导致数据争用。由于存在 taskwait,因此可在执行任务时访问 yy。所以,根据 TS2,自动将 yy 的作用域确定为 SHARED