本节中的 C/C++ 示例说明如何用 OpenMP task 和 taskwait 指令递归计算斐波纳契数。
在本例中,并行区域由四个线程执行。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) 任务。这些任务将由遇到这些任务的线程立即执行,从而减少在池中放置任务的开销。
taskwait 指令可确保在调用 fib() 的同一过程中生成的两个任务(即计算 i 和 j 的任务)在对 fib() 的调用返回之前已完成。
请注意,虽然只有一个线程执行 single 指令(因而只有第一个线程调用 fib()),但是所有四个线程都将参与执行生成的任务和放在池中的任务。
示例 3 使用任务计算斐波纳契数#include <stdio.h> #include <omp.h> #define THRESHOLD 9 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