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.  任务处理

5.1 任务处理模型

5.2 数据环境

5.3 任务处理示例

5.4 编程注意事项

5.4.1 THREADPRIVATE 和线程特定的信息

5.4.2 锁

5.4.3 对堆栈数据的引用

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

7.  作用域检查

8.  性能注意事项

A.  子句在指令中的放置

索引

5.3 任务处理示例

以下 C/C++ 程序说明为什么 OpenMP task 指令和 taskwait 指令可用于递归计算斐波纳契数。

在该示例中,parallel 指令指示一个将由四个线程执行的并行区域。在并行构造中,single 指令用于指示只有其中一个线程将执行调用 fib(n)print 语句。

fib(n) 的调用会生成两个任务(由 task 指令指示)。其中一个任务计算 fib(n-1),另一个任务计算 fib(n-2),将返回值加在一起即可产生由 fib(n) 返回的值。对 fib(n-1)fib(n-2) 的每个调用反过来又会生成两个任务。将会以递归方式生成任务,直到传递到 fib() 的参数小于 2。

请注意每个 task 指令上的 final 子句。如果 final 子句表达式 (n <= THRESHOLD) 求值结果为 true,则生成的任务将为 final 任务。执行最终 (final) 任务期间遇到的所有 task 构造将生成包括 (included)(和最终 (final))任务。因此,当使用参数 n = 9, 8, ..., 2 调用 fib 时,将生成包括 (included) 任务。这些包括 (included) 任务将由遇到这些任务的线程立即执行,从而减少在概念池中放置任务的开销。

taskwait 指令可确保在调用 fib() 的过程中生成的两个任务(即计算 ij 的任务)在对 fib() 的调用返回之前已完成。

请注意,虽然只有一个线程执行 single 指令(因而也只有一个线程对 fib(n) 进行调用),但是所有四个线程都将参与执行生成的任务。

以下示例是使用 Oracle Solaris Studio C++ 编译器编译的。

示例 5-1 任务处理示例:计算斐波纳契数

#include <stdio.h>
#include <omp.h>

#define THRESHOLD 5

int fib(int n)
{
  int i, j;
 
  if (n<2)
    return n;
 
  #pragma omp task shared(i) firstprivate(n) final(n <= THRESHOLD)
  i=fib(n-1);
 
  #pragma omp task shared(j) firstprivate(n) final(n <= THRESHOLD)
  j=fib(n-2);
 
  #pragma omp taskwait
  return i+j;
}


int main()
{
  int n = 30;
  omp_set_dynamic(0);
  omp_set_num_threads(4);
 
  #pragma omp parallel shared(n)
  {
     #pragma omp single
     printf ("fib(%d) = %d\n", n, fib(n));
  }
}

% CC -xopenmp -xO3 task_example.cc

% a.out
fib(30) = 832040