OpenMP: Orphaned Directives

A program containing OpenMP directives begins execution as a single thread. This initial thread executes sequentially until the first parallel construct is encountered.

When the initial thread encounters a parallel construct, it creates a team of threads with the initial thread becoming the master of the team. All threads in the team execute in parallel the statements enclosed by the parallel construct, including all routines called from within the enclosed statements.

Image

The statements enclosed lexically within a construct define the static extend of the constructThe dynamic extend includes all statements encountered by a thread during the execution of a construct, including all called routines.

The situation described above leads us to the possibility of using Orphaned Directives. Directives that are not in the static extent of the parallel construct, but in the dynamic extent, are called orphaned directives. Orphaned directives allow to execute portions of a program in parallel with only the minimal changes to the sequential version of it. Using this functionality, it is possible to code parallel construct  at the top-levels of a program call tree and use directives to control the execution in any of the called routines. In the following example, the for loop is an orphaned directive since the parallel region is not lexically present in routine bar.

int main(void)
{
   #pragma omp parallel
   {
      bar();
   }
}

void bar()
{
   #pragma omp for //this is an orphaned directive
   for(i=0; i<n; i++)
   {
      do_something(i);
   }
}

It is also important to consider along with the usage of orphaned directives, how directives may bind and nest within each other. For more details about that, take a look to the binding and nesting rules defined in the OpenMP standard.