同步构造
THREAD 1:
increment(x) { x = x + 1; } THREAD 1:
10 LOAD A, (x address) 20 ADD A, 1 30 STORE A, (x address) |
THREAD 2:
increment(x) { x = x + 1; } THREAD 2:
10 LOAD A, (x address) 20 ADD A, 1 30 STORE A, (x address) |
1. 线程一加载x到寄存器A
2. 线程二加载x到寄存器A
3. 线程一将寄存器A的值+1
4. 线程二将寄存器A的值+1
5. 线程一将寄存器A的值保存到x
6. 线程二将寄存器A的值保存到x
结果将会是1,而不是期望的2.(注:两个cpu,所以"寄存器 A"不是同一个)
同步构造
MASTER 指令
目的:
格式:
Fortran |
!$OMP MASTER
block
!$OMP END MASTER |
C/C++ |
#pragma omp master newline
structured_block |
限制:
CRITICAL 指令
目的:
格式:
Fortran |
!$OMP CRITICAL [ name ]
block
!$OMP END CRITICAL |
C/C++ |
#pragma omp critical [ name ] newline
structured_block |
注意:
限制:
Example: CRITICAL Construct
Fortran - CRITICAL Directive Example
PROGRAM CRITICAL
INTEGER X X = 0
!$OMP PARALLEL SHARED(X)
!$OMP CRITICAL X = X + 1 !$OMP END CRITICAL
!$OMP END PARALLEL
END |
C / C++ - critical Directive Example
#include
main() {
int x; x = 0;
#pragma omp parallel shared(x) {
#pragma omp critical x = x + 1;
} /* end of parallel section */
} |
BARRIER 指令
目的:
格式:
Fortran |
!$OMP BARRIER |
C/C++ |
#pragma omp barrier newline |
限制:
TASKWAIT 指令
目的:
格式:
Fortran |
!$OMP TASKWAIT |
C/C++ |
#pragma omp taskwait newline |
限制:
ATOMIC 指令
目的:
格式:
Fortran |
!$OMP ATOMIC
statement_expression |
C/C++ |
#pragma omp atomic newline
statement_expression |
限制:
FLUSH 指令
目的:
Q17: !$omp flush指令在一个高速缓存一致的系统上是否必要?
A17:是的,flush指令是必要的,请查看OpenMP规范中的应用示例.指令需要指示编译器相关变量必须对系统内存执行写入/读取操作,也就是说,代码中flush“语句”中的变量不能被保持在一个局部CPU寄存器。高速缓存一致性确保如果一个cpu对内存执行了读/写操作,那么系统中的所有其他CPU在访问此内存地址的时候都会得到相同的值。但是在这点上,OpenMP标准是指示编译器确实插入了读/写机器指令并且没有推迟的一种方法。在为循环产生高效机器代码时,将一个循环中的变量保持在寄存器中是相当普遍的。
更多细节请查看最新的 OpenMP 文献 .
格式:
Fortran |
!$OMP FLUSH (list) |
C/C++ |
#pragma omp flush (list) newline |
注意:
Fortran |
C / C++ |
BARRIER |
barrier |
ORDERED 指令
目的:
格式:
Fortran |
!$OMP DO ORDERED [clauses...] (loop region)
!$OMP ORDERED
(block)
!$OMP END ORDERED
(end of loop region) !$OMP END DO |
C/C++ |
#pragma omp for ordered [clauses...] (loop region)
#pragma omp ordered newline
structured_block
(endo of loop region) |
限制:
THREADPRIVATE 指令
目的:
Format:
Fortran |
!$OMP THREADPRIVATE (/cb/, ...) cb is the name of a common block |
C/C++ |
#pragma omp threadprivate (list) |
注意:
Fortran - THREADPRIVATE Directive Example
PROGRAM THREADPRIV
INTEGER A, B, I, TID, OMP_GET_THREAD_NUM REAL*4 X COMMON /C1/ A
!$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
Output:
1st Parallel Region: Thread 0 : A,B,X= 0 0 1.000000000 Thread 1 : A,B,X= 1 1 2.099999905 Thread 3 : A,B,X= 3 3 4.300000191 Thread 2 : A,B,X= 2 2 3.200000048 ************************************ Master thread doing serial work here ************************************ 2nd Parallel Region: Thread 0 : A,B,X= 0 0 1.000000000 Thread 2 : A,B,X= 2 0 3.200000048 Thread 3 : A,B,X= 3 0 4.300000191 Thread 1 : A,B,X= 1 0 2.099999905 |
C/C++ - threadprivate Directive Example
#include
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 */
}
Output:
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 |
限制:
Fortran:THREADPRIVATE只能作用已命名的公共块 。