XL Fortran for AIX 8.1

Language Reference

THREADPRIVATE

Purpose

The THREADPRIVATE directive allows you to specify named common blocks and named variables as private to a thread but global within that thread. Once you declare a common block or variable THREADPRIVATE, each thread in the team maintains a separate copy of that common block or variable. Data written to a THREADPRIVATE common block or variable remains private to that thread and is not visible to other threads in the team.

In the serial and MASTER sections of a program, only the master thread's copy of the named common block and variable is accessible.

Use the COPYIN clause on the PARALLEL, PARALLEL DO, PARALLEL SECTIONS or PARALLEL WORKSHARE directives to specify that upon entry into a parallel region, data in the master thread's copy of a named common block or named variable is copied to each thread's private copy of that common block or variable.

The THREADPRIVATE directive only takes effect if you specify the -qsmp compiler option.

Format



>>-THREADPRIVATE--(--copyprivate_entity_list--)----------------><
 
 

where copyprivate_entity_list is:

>>-+-variable_name---------+-----------------------------------><
   '-/ common_block_name /-'
 
 

common_block_name
is the name of a common block to be made private to a thread.

variable_name
is the name of a variable to be made private to a thread.

Rules

You cannot specify a THREADPRIVATE variable, common block, or the variables that comprise that common block in a PRIVATE, FIRSTPRIVATE, LASTPRIVATE, SHARED, or REDUCTION clause.

A THREADPRIVATE variable must have the SAVE attribute. For variables or common blocks declared in the scope of a module, the SAVE attribute is implied. If you declare the variable outside of the scope of the module, the SAVE attribute must be specified.

In THREADPRIVATE directives, you can only specify named variables and named common blocks.

A variable can only appear in a THREADPRIVATE directive in the scope in which it is declared, and a THREADPRIVATE variable or common block may only appear once in a given scope. The variable must not be an element of a common block, or be declared in an EQUIVALENCE statement.

You cannot specify the same common_block_name for both a THREADPRIVATE directive and a THREADLOCAL directive.

All rules and constraints that apply to named common blocks also apply to common blocks declared as THREADPRIVATE. See COMMON.

If you declare a common block as THREADPRIVATE in one scoping unit, you must declare it as THREADPRIVATE in all other scoping units in which it is declared.

On entry into any parallel region, a THREADPRIVATE variable, or a variable in a THREADPRIVATE common block is subject to the following criteria when declared in a COPYIN clause:

On entry into the first parallel region of the program, THREADPRIVATE variables or variables within a THREADPRIVATE common block not specified in a COPYIN clause are subject to the following criteria:

On entry into subsequent parallel regions of the program, THREADPRIVATE variables, or variables within a THREADPRIVATE common block not specified in a COPYIN clause, are subject to the following criteria:

You cannot access the name of a common block by use association or host association. Thus, a named common block can only appear on a THREADPRIVATE directive if the common block is declared in the scoping unit that contains the THREADPRIVATE directive. However, you can access the variables in the common block by use association or host association. For more information, see Host Association and Use Association.

The -qinit=f90ptr compiler option does not affect pointers that you have declared in a THREADPRIVATE common block.

The DEFAULT clause does not affect variables in THREADPRIVATE common blocks.

Examples

Example 1: In this example, the PARALLEL DO directive invokes multiple threads that call SUB1. The common block BLK in SUB1 shares the data that is specific to the thread with subroutine SUB2, which is called by SUB1.

      PROGRAM TT
        INTEGER :: I, B(50)
 
!$OMP   PARALLEL DO SCHEDULE(STATIC, 10)
        DO I=1, 50
          CALL SUB1(I, B(I))       ! Multiple threads call SUB1.
        ENDDO
      END PROGRAM TT
 
      SUBROUTINE SUB1(J, X)
        INTEGER :: J, X, A(100)
        COMMON /BLK/ A
!$OMP   THREADPRIVATE(/BLK/)   ! Array a is private to each thread.
!  ...
        CALL SUB2(J)
        X = A(J) + A(J + 50)
!  ...
      END SUBROUTINE SUB1
 
      SUBROUTINE SUB2(K)
        INTEGER :: C(100)
        COMMON /BLK/ C
!$OMP   THREADPRIVATE(/BLK/)
!  ...
        C = K
!  ...                       ! Since each thread has its own copy of
                             ! common block BLK, the assignment of
                             ! array C has no effect on the copies of
                             ! that block owned by other threads.
END SUBROUTINE SUB2

Example 2: In this example, each thread has its own copy of the common block ARR in the parallel section. If one thread initializes the common block variable TEMP, the initial value is not visible to other threads.

      PROGRAM ABC
        INTEGER :: I, TEMP(100), ARR1(50), ARR2(50)
        COMMON /ARR/ TEMP
!$OMP   THREADPRIVATE(/ARR/)
        INTERFACE
          SUBROUTINE SUBS(X)
            INTEGER :: X(:)
          END SUBROUTINE
        END INTERFACE
! ...
!$OMP   PARALLEL SECTIONS
!$OMP   SECTION                   ! The thread has its own copy of the
! ...                             ! common block ARR.
          TEMP(1:100:2) = -1
          TEMP(2:100:2) = 2
          CALL SUBS(ARR1)
! ...
!$OMP   SECTION                   ! The thread has its own copy of the
! ...                             ! common block ARR.
          TEMP(1:100:2) = 1
          TEMP(2:100:2) = -2
          CALL SUBS(ARR2)
! ...
!$OMP    END PARALLEL SECTIONS
! ...
        PRINT *, SUM(ARR1), SUM(ARR2)
      END PROGRAM ABC
 
      SUBROUTINE SUBS(X)
        INTEGER :: K, X(:), TEMP(100)
        COMMON /ARR/ TEMP
!$OMP   THREADPRIVATE(/ARR/)
!  ...
        DO K = 1, UBOUND(X, 1)
          X(K) = TEMP(K) + TEMP(K + 1)    ! The thread is accessing its
                                          ! own copy of
                                          ! the common block.
        ENDDO
! ...
      END SUBROUTINE SUBS

The expected output for this program is:

50 -50

Example 3: In the following example, local variables outside of a common block are declared THREADPRIVATE.

      MODULE MDL
        INTEGER          :: A(2)
        INTEGER, POINTER :: P
        INTEGER, TARGET  :: T
!$OMP THREADPRIVATE(A, P)
      END MODULE MDL
 
 
      PROGRAM MVAR
      USE MDL
 
      INTEGER :: I
      INTEGER OMP_GET_THREAD_NUM
 
      CALL OMP_SET_NUM_THREADS(2)
      A = (/1, 2/)
      T = 4
      P => T
 
!$OMP PARALLEL PRIVATE(I) COPYIN(A, P)
      I = OMP_GET_THREAD_NUM()
      IF (I .EQ. 0) THEN
        A(1) = 100
        T = 5
      ELSE IF (I .EQ. 1) THEN
        A(2) = 200
      END IF
!$OMP END PARALLEL
 
!$OMP PARALLEL PRIVATE(I)
      I = OMP_GET_THREAD_NUM()
      IF (I .EQ. 0) THEN
        PRINT *, 'A(2) = ', A(2)
      ELSE IF (I .EQ. 1) THEN
        PRINT *, 'A(1) = ', A(1)
        PRINT *, 'P => ', P
      END IF
!$OMP END PARALLEL
 
      END PROGRAM MVAR
 

If dynamic threads mechanism is disabled, the expected output is:

A(2) = 2
A(1) = 1
P => 5
or
A(1) = 1
P => 5
A(2) = 2

Related Information


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]