Using OpenMP to Produce a Parallel Application
With OpenMP, directives in the source code are used to express parallel constructs. These directives start with the phrase #pragma omp. Under appropriate compilation flags, they are read by the compiler and used to generate a parallel version of the application. If the required compiler flags are not provided, the directives are ignored. The OpenMP API specification details these directives as well as library calls to determine or modify runtime parameters such as the current number of threads. As we saw in Chapter 3, “Identifying Opportunities for Parallelization,” a benefit of using OpenMP directives is that it sepa-rates the parallelism from the algorithm. The code can be read without having to worry about how the parallelization is implemented. Some other advantages to using OpenMP are as follows:
The directives are recognized only when compiled with a particular compiler flag, so the same source base can be used to generate the serial and parallel versions of the code. This simplifies debugging since it is relatively easy to determine whether, for a given problem, the parallel version produces a different answer to the serial version and therefore whether a bug is because of the parallelization or the origi-nal algorithm.
n Each directive is limited in scope to the region of code to which it applies. Consequently, the developer can focus on making the critical section of the code parallel without having to be concerned about changing the rest of the code to support this parallelization. This is often referred to as the ability to perform incremental parallelization.
n Possibly the biggest advantage is that the compiler and supporting library are responsible for all the parallelization work and the runtime management of threads.
It is probably easiest to demonstrate the use of OpenMP directives through the simple example shown in Listing 7.21. The OpenMP directive is indicated in bold.
Listing 7.21 Loop Parallelized Using OpenMP
void calc( double* array1, double * array2, int length )
#pragma omp parallel for
for ( int i=0; i<length; i++ )
array1[i] += array2[i];
The code in Listing 7.21 shows how the OpenMP directive can be placed above the loop to which it applies. The OpenMP directive places the burden of ensuring the code is safe to execute in parallel on the developer, not on the compiler. Although the com-piler will produce a parallel version of the loop, it is up to the developer to ensure that this is a safe optimization to make. An instance of where this might be unsafe is if the two arrays had some degree of overlap, then the parallel version might not produce the same result as the serial version.
The OpenMP directive has three parts:
n #pragma omp indicates to the compiler that what follows is an OpenMP directive.
n parallel tells the compiler to start a new parallel region. Unless otherwise specified, all the threads will execute the code in the parallel region.
n for tells the compiler that the next for loop should be executed in parallel.
Multiple threads will work on independent parts of the range of iterations. At the end of the loop, the threads will wait until all the iterations have completed before the next part of the code is executed.
The statement given in this code snippet is the simplest possible example, but it illus-trates exactly what the OpenMP specification aims to achieve.
Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.