10.1. threadprivate Directive#

The following examples demonstrate how to use the threadprivate directive to give each thread a separate counter.

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

/*
* name: threadprivate.1
* type: C
*/
int counter = 0;
#pragma omp threadprivate(counter)

int increment_counter()
{
  counter++;
  return(counter);
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: threadprivate.1
! type: F-fixed
      INTEGER FUNCTION INCREMENT_COUNTER()
        COMMON/INC_COMMON/COUNTER
!$OMP   THREADPRIVATE(/INC_COMMON/)

        COUNTER = COUNTER +1
        INCREMENT_COUNTER = COUNTER
        RETURN
      END FUNCTION INCREMENT_COUNTER

The following example uses threadprivate on a static variable:

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

/*
* name: threadprivate.2
* type: C
*/
int increment_counter_2()
{
  static int counter = 0;
  #pragma omp threadprivate(counter)
  counter++;
  return(counter);
}

The following example demonstrates unspecified behavior for the initialization of a threadprivate variable. A threadprivate variable is initialized once at an unspecified point before its first reference. Because a is constructed using the value of x (which is modified by the statement x++), the value of a.val at the start of the parallel region could be either 1 or 2. This problem is avoided for b, which uses an auxiliary const variable and a copy-constructor.

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

/*
* name: threadprivate.3
* type: C++
*/
class T {
  public:
    int val;
    T (int);
    T (const T&);
};

T :: T (int v){
   val = v;
}

T :: T (const T& t) {
   val = t.val;
}

void g(T a, T b){
   a.val += b.val;
}

int x = 1;
T a(x);
const T b_aux(x); /* Capture value of x = 1 */
T b(b_aux);
#pragma omp threadprivate(a, b)

void f(int n) {
   x++;
   #pragma omp parallel for
   /* In each thread:
    * a is constructed from x (with value 1 or 2?)
    * b is copy-constructed from b_aux
    */

   for (int i=0; i<n; i++) {
       g(a, b); /* Value of a is unspecified. */
   }
}

The following examples show non-conforming uses and correct uses of the threadprivate directive.

The following example is non-conforming because the common block is not declared local to the subroutine that refers to it:

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

! name: threadprivate.2
! type: F-fixed
      MODULE INC_MODULE
        COMMON /T/ A
      END MODULE INC_MODULE

      SUBROUTINE INC_MODULE_WRONG()
        USE INC_MODULE
!$OMP   THREADPRIVATE(/T/)
      !non-conforming because /T/ not declared in INC_MODULE_WRONG
      END SUBROUTINE INC_MODULE_WRONG

The following example is also non-conforming because the common block is not declared local to the subroutine that refers to it:

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

! name: threadprivate.3
! type: F-fixed
      SUBROUTINE INC_WRONG()
        COMMON /T/ A
!$OMP   THREADPRIVATE(/T/)

        CONTAINS
          SUBROUTINE INC_WRONG_SUB()
!$OMP       PARALLEL COPYIN(/T/)
      !non-conforming because /T/ not declared in INC_WRONG_SUB
!$OMP       END PARALLEL
          END SUBROUTINE INC_WRONG_SUB
      END SUBROUTINE INC_WRONG

The following example is a correct rewrite of the previous example:

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

! name: threadprivate.4
! type: F-fixed
       SUBROUTINE INC_GOOD()
        COMMON /T/ A
!$OMP   THREADPRIVATE(/T/)

        CONTAINS
          SUBROUTINE INC_GOOD_SUB()
            COMMON /T/ A
!$OMP       THREADPRIVATE(/T/)

!$OMP       PARALLEL COPYIN(/T/)
!$OMP       END PARALLEL
         END SUBROUTINE INC_GOOD_SUB
       END SUBROUTINE INC_GOOD

The following is an example of the use of threadprivate for local variables:

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

! name: threadprivate.5
! type: F-fixed
      PROGRAM INC_GOOD2
        INTEGER, ALLOCATABLE, SAVE :: A(:)
        INTEGER, POINTER, SAVE :: PTR
        INTEGER, SAVE :: I
        INTEGER, TARGET :: TARG
        LOGICAL :: FIRSTIN = .TRUE.
!$OMP   THREADPRIVATE(A, I, PTR)

        ALLOCATE (A(3))
        A = (/1,2,3/)
        PTR => TARG
        I = 5

!$OMP   PARALLEL COPYIN(I, PTR)
!$OMP     CRITICAL
            IF (FIRSTIN) THEN
              TARG = 4           ! Update target of ptr
              I = I + 10
              IF (ALLOCATED(A)) A = A + 10
              FIRSTIN = .FALSE.
            END IF

            IF (ALLOCATED(A)) THEN
              PRINT *, 'a = ', A
            ELSE
              PRINT *, 'A is not allocated'
            END IF

            PRINT *, 'ptr = ', PTR
            PRINT *, 'i = ', I
            PRINT *

!$OMP     END CRITICAL
!$OMP   END PARALLEL
      END PROGRAM INC_GOOD2

The above program, if executed by two threads, will print one of the following two sets of output:

a = 11 12 13
ptr = 4 i = 15

A is not allocated
ptr = 4
i = 5

or

A is not allocated
ptr = 4
i = 15

a = 1 2 3
ptr = 4
i = 5

The following is an example of the use of threadprivate for module variables:

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

! name: threadprivate.6
! type: F-fixed
      MODULE INC_MODULE_GOOD3
        REAL, POINTER :: WORK(:)
        SAVE WORK
!$OMP   THREADPRIVATE(WORK)
      END MODULE INC_MODULE_GOOD3

      SUBROUTINE SUB1(N)
      USE INC_MODULE_GOOD3
!$OMP   PARALLEL PRIVATE(THE_SUM)
        ALLOCATE(WORK(N))
        CALL SUB2(THE_SUM)
       WRITE(*,*)THE_SUM
!$OMP   END PARALLEL
      END SUBROUTINE SUB1

      SUBROUTINE SUB2(THE_SUM)
        USE INC_MODULE_GOOD3
        WORK(:) = 10
        THE_SUM=SUM(WORK)
      END SUBROUTINE SUB2

      PROGRAM INC_GOOD3
        N = 10
        CALL SUB1(N)
      END PROGRAM INC_GOOD3

The following example illustrates initialization of threadprivate variables for class-type T. t1 is default constructed, t2 is constructed taking a constructor accepting one argument of integer type, t3 is copy constructed with argument f():

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

/*
* name: threadprivate.4
* type: C++
*/
struct T { T (); T (int); ~T (); int t; };
int f();
static T t1;
#pragma omp threadprivate(t1)
static T t2( 23 );
#pragma omp threadprivate(t2)
static T t3 = f();
#pragma omp threadprivate(t3)

The following example illustrates the use of threadprivate for static class members. The threadprivate directive for a static class member must be placed inside the class definition.

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

/*
* name: threadprivate.5
* type: C++
*/
class T {
 public:
  static int i;
#pragma omp threadprivate(i)
};