JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Studio 12.3: OpenMP API User's Guide     Oracle Solaris Studio 12.3 Information Library
search filter icon
search icon

Document Information

Preface

1.  Introducing the OpenMP API

2.  Compiling and Running OpenMP Programs

3.  Implementation-Defined Behaviors

4.  Nested Parallelism

5.  Tasking

5.1 Tasking Model

5.2 Data Environment

5.3 Tasking Example

5.4 Programming Considerations

5.4.1 THREADPRIVATE and Thread-Specific Information

5.4.2 Locks

5.4.3 References to Stack Data

6.  Automatic Scoping of Variables

7.  Scope Checking

8.  Performance Considerations

A.  Placement of Clauses on Directives

Index

5.3 Tasking Example

The following C/C++ program illustrates how the OpenMP task and taskwait directives can be used to compute Fibonacci numbers recursively.

In the example, the parallel directive denotes a parallel region which will be executed by four threads. In the parallel construct, the single directive is used to indicate that only one of the threads will execute the print statement that calls fib(n).

The call to fib(n) generates two tasks, indicated by the task directive. One of the tasks computes fib(n-1) and the other computes fib(n-2) The return values are added together to produce the value returned by fib(n). Each of the calls to fib(n-1) and fib(n-2) will in turn generate two tasks. Tasks will be recursively generated until the argument passed to fib() is less than 2.

Note the final clause on each of the task directives. If the final clause expression (n <= THRESHOLD) evaluates to true, then the generated task will be a final task. All task constructs encountered during execution of a final task will generate included (and final) tasks. So included tasks will be generated when fib is called with the argument n = 9, 8, ..., 2. These included tasks will be executed immediately by the encountering threads, thus reducing the overhead of placing tasks in the conceptual pool.

The taskwait directive ensures that the two tasks generated in an invocation of fib() are completed (that is, the tasks compute i and j) before that invocation of fib() returns.

Note that although only one thread executes the single directive and hence the call to fib(n), all four threads will participate in executing the tasks generated.

The following example is compiled using the Oracle Solaris Studio C++ compiler.

Example 5-1 Tasking Example: Computing Fibonacci Numbers

#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