THREADPRIVATE
用途
THREADPRIVATE 指引可讓您將具名共用區塊及具名變數指定為執行緒專用,但在該執行緒內是廣域的。 一旦您宣告共同區塊或變數 THREADPRIVATE,團隊中的每一個執行緒都會維護該共同區塊或變數的個別副本。 寫入 THREADPRIVATE 共用區塊或變數的資料會保持該執行緒的專用狀態,且不會對團隊中的其他執行緒顯示。
在程式的序列及 MASTER 區段中,只能存取 主要 執行緒的具名共用區塊及變數副本。
在 PARALLEL、 PARALLEL DO、 PARALLEL SECTIONS 或 PARALLEL WORKSHARE 指引上使用 COPYIN 子句,指定在進入平行區域時, 主要 執行緒的具名共用區塊或具名變數副本中的資料會複製到每個執行緒的該共用區塊或變數專用副本。
必要選項
-qsmp
語法
規則
您無法在 PRIVATE、 FIRSTPRIVATE、 LASTPRIVATE、 SHARED或 REDUCTION 子句中指定 THREADPRIVATE 變數、共用區塊或組成該共用區塊的變數。
THREADPRIVATE 變數必須具有 SAVE 屬性。 對於模組範圍中宣告的變數或一般區塊,隱含有 SAVE 屬性。 如果您在模組範圍之外宣告變數,則必須指定 SAVE 屬性。
在 THREADPRIVATE 指引中,您只能指定具名變數及具名共用區塊。
變數只能出現在其宣告範圍內的 THREADPRIVATE 指引中,而 THREADPRIVATE 變數或共同區塊在給定範圍內只能出現一次。 變數不能是共同區塊的元素,也不能在 EQUIVALENCE 陳述式中宣告。
您不能同時對 THREADPRIVATE 指引和 THREADLOCAL 指引指定相同的 common_block_name 。
適用於具名共用區塊的所有規則及限制也適用於宣告為 THREADPRIVATE的共用區塊。 請參閱 COMMON 陳述式 。
如果您在一個範圍設定單元中將共用區塊宣告為 THREADPRIVATE ,則必須在宣告它的所有其他範圍設定單元中將它宣告為 THREADPRIVATE 。
如果您使用 BIND 屬性來宣告 THREADPRIVATE 變數或 THREADPRIVATE 共用區塊,則必須在 C 程式的 THREADPRIVATE 指引中指定對應的 C 實體。 如需詳細用法資訊,請參閱 範例 4 。
進入任何平行區域時,在 COPYIN 子句中指定的 THREADPRIVATE 共同區塊中的 THREADPRIVATE 變數或變數會受到 COPYIN 子句的 Rules 區段中所述的準則所規範。
- 如果變數具有 ALLOCATABLE 屬性,則目前不會配置該變數每一個副本的起始配置狀態。
- 如果變數具有 POINTER 屬性,且該指標透過明確或預設起始設定取消關聯,則該變數的每一個副本的關聯狀態會取消關聯。 否則,指標的關聯狀態未定義。
- 如果變數既沒有 ALLOCATABLE 也沒有 POINTER 屬性,而且是透過明確或預設起始設定來定義,則會定義該變數的每一個副本。 如果變數未定義,則該變數的每一個副本都未定義。
- 如果您使用 OMP_DYNAMIC 環境變數或 omp_set_dynamic 子常式來啟用動態執行緒及:
- 如果執行緒數目小於前一個區域中的執行緒數目,且在兩個區域中都參照 THREADPRIVATE 物件,則在其各自區域中具有相同執行緒數目的執行緒會參照該變數的相同副本。
- 如果執行緒數目大於前一個區域中的執行緒數目,則未定義 THREADPRIVATE 物件的定義及關聯狀態,且未定義配置狀態。
- 如果停用動態執行緒,則會保留定義、關聯或配置狀態及定義 (如果已定義執行緒的變數副本)。
您無法透過使用關聯或主機關聯來存取共用區塊的名稱。 因此,如果共用區塊在包含 THREADPRIVATE 指引的範圍設定單元中宣告,則具名共用區塊只能出現在 THREADPRIVATE 指引上。 不過,您可以使用關聯或主機關聯來存取共用區塊中的變數。 如需相關資訊,請參閱 主機 及 使用關聯 。
-qinit=f90ptr 編譯器選項不會影響您在 THREADPRIVATE 共用區塊中宣告的指標。
DEFAULT 子句不會影響 THREADPRIVATE 共同區塊中的變數。
範例
Example 1: 在此範例中, PARALLEL DO 指引會呼叫多個呼叫 SUB1的執行緒。 SUB1 中的共用區塊 BLK 與子常式 SUB2(由 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 SUB2Example 2: 在此範例中,每一個執行緒在平行區段中都有自己的共同區塊副本 ARR 。 如果一個執行緒起始設定一般區塊變數 TEMP,則其他執行緒無法看到起始值。
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此程式的預期輸出為:
50 -50Example 3: 在下列範例中,共同區塊外部的區域變數宣告為 THREADPRIVATE。
MODULE MDL
INTEGER :: A(2)
INTEGER, POINTER :: P
INTEGER, TARGET :: T
!$OMP THREADPRIVATE(A, P)
END MODULE MDL
PROGRAM MVAR
USE OMP_LIB
USE MDL
INTEGER :: I
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
A(2) = 2
A(1) = 1
P => 5
or
A(1) = 1
P => 5
A(2) = 2Example 4: 在此範例中, C 可交互作業變數 NUMVAR 宣告為 THREADPRIVATE。 執行緒 1 對 NUMVAR 的專用副本所做的變更不會影響 主要 執行緒的副本。
Fortran 原始檔 MODULE M
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT), BIND(C) :: NUMVAR(10)
!$OMP THREADPRIVATE(NUMVAR)
END MODULE M
PROGRAM P
USE M
USE OMP_LIB
INTERFACE
SUBROUTINE INIT_NUM() BIND(C)
END SUBROUTINE INIT_NUM
SUBROUTINE PRINT_NUM() BIND(C)
END SUBROUTINE PRINT_NUM
END INTERFACE
INTEGER TNUM
CALL INIT_NUM()
CALL OMP_SET_NUM_THREADS(2)
!$OMP PARALLEL COPYIN(NUMVAR)
TNUM = OMP_GET_THREAD_NUM()
IF (TNUM .EQ. 0) THEN
! PROCESS NUMVAR
ELSE IF (TNUM .EQ. 1) THEN
NUMVAR = NUMVAR * 4
CALL PRINT_NUM()
! PROCESS NUMVAR
END IF
!$OMP END PARALLEL
CALL PRINT_NUM()
END PROGRAM PC source file
#include <stdio.h>
extern int numvar[10];
#pragma omp threadprivate(numvar)
void init_num(){
for (int i = 0; i < 10; ++ i)
numvar[i] = i * i;
}
void print_num(){
for (int i = 0; i < 10; ++ i)
printf("%d ", numvar[i]);
printf("\n");
}0 4 16 36 64 100 144 196 256 324
0 1 4 9 16 25 36 49 64 81