用Fortran实现OpenMP约简中的变量局部性



这是我的Fortran代码的一部分。

iabcd=0
!$OMP PARALLEL DEFAULT(PRIVATE) SHARED(icheck,iv,HO,tnljm,H)
!$OMP DO SCHEDULE(DYNAMIC) REDUCTION(+: iabcd)
do ia=1,HO%NLEV 
do ib=ia+1,HO%NLEV
do ic=1,HO%NLEV
do id=ic+1,HO%NLEV
if(tnljm%t(ia)+tnljm%t(ib) .ne. tnljm%t(ic)+tnljm%t(id)) cycle 
iabcd = iabcd + 1
H%ka(iabcd) = ia
H%kb(iabcd) = ib
H%kc(iabcd) = ic
H%kd(iabcd) = id
H%ME2BM(iabcd) = 0.d0
enddo
enddo
enddo
enddo
!$OMP END DO
!$OMP END PARALLEL

我可以在没有任何警告的情况下运行代码。但是,结果很奇怪,与不使用OpenMP的结果不同。代码有什么问题?谢谢

使用OMP DO REDUCTION(+:iabc)时,每个线程都会创建自己的私有变量iabc,并在循环中使用该变量,只有在处理了并行区域后,才会进行添加。

也就是说,访问

H%ka(iabcd) = ia
H%kb(iabcd) = ib
H%kc(iabcd) = ic
H%kd(iabcd) = id
H%ME2BM(iabcd) = 0.d0

仅使用iabc的本地专用版本,这与代码的串行版本不同。

相反,您可以使用OMP CRITICAL来更新iabc,因为您希望所有线程都使用相同版本的iabc(当然,还可以共享iabc(。然后,您还必须在关键区域内创建iabc的专用副本,以便使用正确的iabc更新H。然而,这将降低并行化的效率,除非tnljm%t(ia)+tnljm%t(ib) .ne. tnljm%t(ic)+tnljm%t(id)几乎总是真的。

最新更新