9.1. critical Construct#

The following example includes several critical constructs. The example illustrates a queuing model in which a task is dequeued and worked on. To guard against multiple threads dequeuing the same task, the dequeuing operation must be in a critical region. Because the two queues in this example are independent, they are protected by critical constructs with different names, xaxis and yaxis .

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

/*
* name: critical.1
* type: C
*/
int dequeue(float *a);
void work(int i, float *a);

void critical_example(float *x, float *y)
{
  int ix_next, iy_next;

  #pragma omp parallel shared(x, y) private(ix_next, iy_next)
  {
    #pragma omp critical (xaxis)
      ix_next = dequeue(x);
    work(ix_next, x);

    #pragma omp critical (yaxis)
      iy_next = dequeue(y);
    work(iy_next, y);
  }

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

! name: critical.1
! type: F-fixed
      SUBROUTINE CRITICAL_EXAMPLE(X, Y)

        REAL X(*), Y(*)
        INTEGER IX_NEXT, IY_NEXT

!$OMP PARALLEL SHARED(X, Y) PRIVATE(IX_NEXT, IY_NEXT)

!$OMP CRITICAL(XAXIS)
        CALL DEQUEUE(IX_NEXT, X)
!$OMP END CRITICAL(XAXIS)
        CALL WORK(IX_NEXT, X)

!$OMP CRITICAL(YAXIS)
        CALL DEQUEUE(IY_NEXT,Y)
!$OMP END CRITICAL(YAXIS)
        CALL WORK(IY_NEXT, Y)

!$OMP END PARALLEL

      END SUBROUTINE CRITICAL_EXAMPLE

The following example extends the previous example by adding the hint clause to the critical constructs.

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

/*
* name: critical.2
* type: C
* version: omp_5.0
*/
#include <omp.h>

int dequeue(float *a);
void work(int i, float *a);

void critical_example(float *x, float *y)
{
  int ix_next, iy_next;

  #pragma omp parallel shared(x, y) private(ix_next, iy_next)
  {
    #pragma omp critical (xaxis) hint(omp_sync_hint_contended)
      ix_next = dequeue(x);
    work(ix_next, x);

    #pragma omp critical (yaxis) hint(omp_sync_hint_contended)
      iy_next = dequeue(y);
    work(iy_next, y);
  }

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

! name: critical.2
! type: F-fixed
! version: omp_5.0
      SUBROUTINE CRITICAL_EXAMPLE(X, Y)
        USE OMP_LIB        ! or INCLUDE "omp_lib.h"

        REAL X(*), Y(*)
        INTEGER IX_NEXT, IY_NEXT

!$OMP PARALLEL SHARED(X, Y) PRIVATE(IX_NEXT, IY_NEXT)

!$OMP CRITICAL(XAXIS) HINT(OMP_SYNC_HINT_CONTENDED)
        CALL DEQUEUE(IX_NEXT, X)
!$OMP END CRITICAL(XAXIS)
        CALL WORK(IX_NEXT, X)

!$OMP CRITICAL(YAXIS) HINT(OMP_SYNC_HINT_CONTENDED)
        CALL DEQUEUE(IY_NEXT,Y)
!$OMP END CRITICAL(YAXIS)
        CALL WORK(IY_NEXT, Y)

!$OMP END PARALLEL

      END SUBROUTINE CRITICAL_EXAMPLE