Loop Construct
OpenMP loop constructs are introduced by the for
directive in the C/C++ context and the do
directive in Fortran, matching the usual keywords for loops in the respective languages. These directives begin with the OpenMP comment sentinel and are optionally followed by modifying clauses. The extent of the for construct is the extent of the loop that immediately follows it. The extent of a do construct is also the extent of the do loop that immediately follows it, but the OpenMP standard allows Fortran programs to contain an END DO
directive following the do loop. The OpenMP loop directives are illegal outside of a parallel region, but if the parallel region coincides with the loop region, the parallel and loop directives can be combined as
#pragma omp parallel for [clauses]
for C, or a corresponding combination for Fortran.
#pragma omp parallel [clause [,clause]]
{
⋮
#pragma omp for [clause [,clause]]
{
⋮
}
⋮
}
!$OMP PARALLEL [clause [,clause]]
⋮
!$OMP DO [clause [,clause]]
DO I=1,1000000
⋮
ENDDO
!$OMP END DO [NOWAIT]
⋮
!$OMP END PARALLEL
Be aware that there are restrictions on loops controlled by an OpenMP loop directive:
- The iteration variable must not be changed within the loop except through the increment expression in the loop statement.
- The initial value and limit for the iteration variable must be constants that can be evaluated before the loop begins, as the OpenMP code uses them in scheduling execution of the iterations on the available threads.
If the iteration variable would otherwise be shared, it is implicitly made private. Note, however, that the iteration variables for nested loops, if they are declared outside the parallel region, will not be made private by default. The final value of the iteration variable will not be available outside the loop construct unless it is listed in a lastprivate clause.
It is never advisable to branch into a loop, but breaking out of loops is common practice in serial code. That is not allowed in a loop that is controlled by an OpenMP loop construct. It is OK to break out of a loop nested inside an OpenMP loop. Branching out of an OpenMP loop to call an error-handler is allowed, but if this should happen, OpenMP will automatically terminate the threads that are processing the rest of the loop.
Since OpenMP 3.0 it is possible to have nested parallel loops, and more generally, nested parallel regions:
However, just because you can have them, doesn't mean you necessarily should - this design might work well for algorithms that are fundamentally limited in the amount of work that can be done at certain points, but usually we want to keep cores saturated by threads in parallel regions, which implies having the same number of threads in most parallel regions. There are exceptions on KNL; the suggested number of threads to run per core is 2-4, which depends on the nature of the work being done. In some regions of your code, it may be more efficient to launch additional threads to saturate the KNL core.