12.9. Restrictions on Nesting of Regions#

The examples in this section illustrate the region nesting rules.

The following example is non-conforming because the inner and outer loop regions are closely nested:

//%compiler: clang
//%cflags: -fopenmp

/*
* name: nesting_restrict.1
* type: C
*/

void work(int i, int j) {}

void wrong1(int n)
{

  #pragma omp parallel default(shared)
  {
    int i, j;
    #pragma omp for
    for (i=0; i<n; i++) {
       /* incorrect nesting of loop regions */
       #pragma omp for
         for (j=0; j<n; j++)
           work(i, j);
    }
  }

}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: nesting_restrict.1
! type: F-fixed

      SUBROUTINE WORK(I, J)
      INTEGER I, J

      END SUBROUTINE WORK

      SUBROUTINE WRONG1(N)

      INTEGER N
      INTEGER I,J
!$OMP   PARALLEL DEFAULT(SHARED)
!$OMP     DO
          DO I = 1, N
!$OMP       DO             ! incorrect nesting of loop regions
            DO J = 1, N
              CALL WORK(I,J)
            END DO
          END DO
!$OMP   END PARALLEL

      END SUBROUTINE WRONG1

The following orphaned version of the preceding example is also non-conforming:

//%compiler: clang
//%cflags: -fopenmp

/*
* name: nesting_restrict.2
* type: C
*/
void work(int i, int j) {}
void work1(int i, int n)
{
  int j;
/* incorrect nesting of loop regions */
  #pragma omp for
    for (j=0; j<n; j++)
      work(i, j);
}

void wrong2(int n)
{
  #pragma omp parallel default(shared)
  {
    int i;
    #pragma omp for
      for (i=0; i<n; i++)
         work1(i, n);
  }
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: nesting_restrict.2
! type: F-fixed
       SUBROUTINE WORK1(I,N)
       INTEGER I, N
       INTEGER J
!$OMP   DO      ! incorrect nesting of loop regions
        DO J = 1, N
          CALL WORK(I,J)
        END DO
       END SUBROUTINE WORK1
       SUBROUTINE WRONG2(N)
       INTEGER N
       INTEGER I
!$OMP   PARALLEL DEFAULT(SHARED)
!$OMP     DO
          DO I = 1, N
            CALL WORK1(I,N)
          END DO
!$OMP   END PARALLEL
       END SUBROUTINE WRONG2

The following example is non-conforming because the loop and single regions are closely nested:

//%compiler: clang
//%cflags: -fopenmp

/*
* name: nesting_restrict.3
* type: C
*/
void work(int i, int j) {}
void wrong3(int n)
{
  #pragma omp parallel default(shared)
  {
    int i;
    #pragma omp for
      for (i=0; i<n; i++) {
/* incorrect nesting of regions */
        #pragma omp single
          work(i, 0);
      }
  }
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: nesting_restrict.3
! type: F-fixed
      SUBROUTINE WRONG3(N)
      INTEGER N

        INTEGER I
!$OMP   PARALLEL DEFAULT(SHARED)
!$OMP     DO
          DO I = 1, N
!$OMP       SINGLE            ! incorrect nesting of regions
              CALL WORK(I, 1)
!$OMP       END SINGLE
          END DO
!$OMP   END PARALLEL
      END SUBROUTINE WRONG3

The following example is non-conforming because a barrier region cannot be closely nested inside a loop region:

//%compiler: clang
//%cflags: -fopenmp

/*
* name: nesting_restrict.4
* type: C
*/
void work(int i, int j) {}
void wrong4(int n)
{

  #pragma omp parallel default(shared)
  {
    int i;
    #pragma omp for
      for (i=0; i<n; i++) {
        work(i, 0);
/* incorrect nesting of barrier region in a loop region */
        #pragma omp barrier
        work(i, 1);
      }
  }
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: nesting_restrict.4
! type: F-fixed
      SUBROUTINE WRONG4(N)
      INTEGER N

        INTEGER I
!$OMP   PARALLEL DEFAULT(SHARED)
!$OMP     DO
          DO I = 1, N
            CALL WORK(I, 1)
! incorrect nesting of barrier region in a loop region
!$OMP       BARRIER
            CALL WORK(I, 2)
          END DO
!$OMP   END PARALLEL
      END SUBROUTINE WRONG4

The following example is non-conforming because the barrier region cannot be closely nested inside the critical region. If this were permitted, it would result in deadlock due to the fact that only one thread at a time can enter the critical region:

//%compiler: clang
//%cflags: -fopenmp

/*
* name: nesting_restrict.5
* type: C
*/
void work(int i, int j) {}
void wrong5(int n)
{
  #pragma omp parallel
  {
    #pragma omp critical
    {
       work(n, 0);
/* incorrect nesting of barrier region in a critical region */
       #pragma omp barrier
       work(n, 1);
    }
  }
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: nesting_restrict.5
! type: F-fixed
      SUBROUTINE WRONG5(N)
      INTEGER N

!$OMP   PARALLEL DEFAULT(SHARED)
!$OMP     CRITICAL
            CALL WORK(N,1)
! incorrect nesting of barrier region in a critical region
!$OMP       BARRIER
            CALL WORK(N,2)
!$OMP     END CRITICAL
!$OMP   END PARALLEL
      END SUBROUTINE WRONG5

The following example is non-conforming because the barrier region cannot be closely nested inside the single region. If this were permitted, it would result in deadlock due to the fact that only one thread executes the single region:

//%compiler: clang
//%cflags: -fopenmp

/*
* name: nesting_restrict.6
* type: C
*/
void work(int i, int j) {}
void wrong6(int n)
{
  #pragma omp parallel
  {
    #pragma omp single
    {
      work(n, 0);
/* incorrect nesting of barrier region in a single region */
      #pragma omp barrier
      work(n, 1);
    }
  }
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: nesting_restrict.6
! type: F-fixed
      SUBROUTINE WRONG6(N)
      INTEGER N

!$OMP   PARALLEL DEFAULT(SHARED)
!$OMP     SINGLE
            CALL WORK(N,1)
! incorrect nesting of barrier region in a single region
!$OMP       BARRIER
            CALL WORK(N,2)
!$OMP     END SINGLE
!$OMP   END PARALLEL
      END SUBROUTINE WRONG6