Директива THREADPRIVATE применяется для того, чтобы создать для глобальных переменных языка C/C++ и COMMON блоков языка Фортран их локальные копии в каждой нити.
C/C++:
#pragma omp threadprivate(list)
Fortran:
!$OMP THREADPRIVATE(list)
Директива THREADPRIVATE вызывается сразу после описания переменных и COMMON блоков. При создании параллельных областей каждая нить будет иметь собственную копию этих объектов. Их модификация каждой нитью не будет видна для других нитей. В языке Фортран допускается включение переменных (помимо COMMON блоков) в список list, но тогда они должны быть описаны как SAVE. Если необходимо переменную, объявленную как THREADPRIVATE, инициализировать значением переменной из нити-мастера, то на входе в параллельную область можно использовать опцию COPYIN. Если значение локальной переменной или переменной, объявленной как THREADPRIVATE, необходимо переслать от одной нити всем, работающим в данной параллельной области, для этого можно использовать опцию COPYPRIVATE директивы SINGLE.
Приведем примеры программы использования этой директивы с результатами ее выполнения.
Программа threadprivate.c
#include <omp.h> int a, b, i, tid; float x; #pragma omp threadprivate(a, x) main () { /* Explicitly turn off dynamic threads */ omp_set_dynamic(0); printf("1st Parallel Region:\n"); #pragma omp parallel private(b,tid) { tid = omp_get_thread_num(); a = tid; b = tid; x = 1.1 * tid +1.0; printf("Thread %d: a,b,x= %d %d %f\n",tid,a,b,x); } /* end of parallel section */ printf("************************************\n"); printf("Master thread doing serial work here\n"); printf("************************************\n"); printf("2nd Parallel Region:\n"); #pragma omp parallel private(tid) { tid = omp_get_thread_num(); printf("Thread %d: a,b,x= %d %d %f\n",tid,a,b,x); } /* end of parallel section */ }
Результат работы (выдача в стандартный выходной поток):
1st Parallel Region: Thread 0: a,b,x= 0 0 1.000000 Thread 2: a,b,x= 2 2 3.200000 Thread 3: a,b,x= 3 3 4.300000 Thread 1: a,b,x= 1 1 2.100000 ************************************ Master thread doing serial work here ************************************ 2nd Parallel Region: Thread 0: a,b,x= 0 0 1.000000 Thread 3: a,b,x= 3 0 4.300000 Thread 1: a,b,x= 1 0 2.100000 Thread 2: a,b,x= 2 0 3.200000
Программа threadprivate.f
PROGRAM threadprivate INTEGER A, B, I, TID, OMP_GET_THREAD_NUM REAL*4 X COMMON /C1/ A SAVE X !$OMP THREADPRIVATE(/C1/, X) C Explicitly turn off dynamic threads CALL OMP_SET_DYNAMIC(.FALSE.) PRINT *, '1st Parallel Region:' !$OMP PARALLEL PRIVATE(B, TID) TID = OMP_GET_THREAD_NUM() A = TID B = TID X = 1.1 * TID + 1.0 PRINT *, 'Thread',TID,': A,B,X=',A,B,X !$OMP END PARALLEL PRINT *, '************************************' PRINT *, 'Master thread doing serial work here' PRINT *, '************************************' PRINT *, '2nd Parallel Region: ' !$OMP PARALLEL PRIVATE(TID) TID = OMP_GET_THREAD_NUM() PRINT *, 'Thread',TID,': A,B,X=',A,B,X !$OMP END PARALLEL END
Результат работы:
1st Parallel Region: Thread 0 : A,B,X= 0 0 1.000000 Thread 1 : A,B,X= 1 1 2.100000 Thread 3 : A,B,X= 3 3 4.300000 Thread 2 : A,B,X= 2 2 3.200000 ************************************ Master thread doing serial work here ************************************ 2nd Parallel Region: Thread 0 : A,B,X= 0 32767 1.000000 Thread 3 : A,B,X= 3 32767 4.300000 Thread 2 : A,B,X= 2 32767 3.200000 Thread 1 : A,B,X= 1 32767 2.100000