我一直在尝试使用简单的代码来使用OpenACC,但我想我并不完全理解如何编写嵌套的OpenACC循环或私有代码。我正在尝试并行化的例程是:
7923
实际上,代码表现良好,如果我在调用此例程后比较zc矩阵,则非OpenACC和OpenACC版本都给出相同的答案。但是,如果我尝试使用并行指令,那么似乎存在竞争条件,我无法弄清楚它在哪里。相关的变化只是:
SUBROUTINE zcs(zc,kmin,kmax,ju2,jl2)
INTEGER, INTENT(IN) :: kmin,kmax,ju2,jl2
DOUBLE PRECISION, DIMENSION(-jl2:jl2,-jl2:jl2,-ju2:ju2,-ju2:ju2,kmin:kmax,kmin:kmax,-kmax:kmax) :: zc
INTEGER :: k,kp,k2,km,kp2,q,q2,mu2,ml2,p2,mup2,pp2,mlp2,ps2,pt2
DOUBLE PRECISION :: z0,z1,z2,z3,z4,z5,z6,z7
! Start loop over K, K' and Q
!$acc kernels
do k=kmin,kmax
do kp=kmin,kmax
k2=2*k
km = MIN(k,kp)
kp2=2*kp
z0=3.d0*dble(ju2+1)*dsqrt(dble(k2+1))*dsqrt(dble(kp2+1))
do q=-km,km
q2=2*q
! Calculate quantity C and its sum over magnetic quantum numbers
do mu2=-ju2,ju2,2
do ml2=-jl2,jl2,2
p2=mu2-ml2
if(abs(p2).gt.2) cycle
z1=w3js(ju2,jl2,2,mu2,-ml2,-p2)
do mup2=-ju2,ju2,2
if(mu2-mup2.ne.q2) cycle
pp2=mup2-ml2
if(abs(pp2).gt.2) cycle
z2=w3js(ju2,jl2,2,mup2,-ml2,-pp2)
do mlp2=-jl2,jl2,2
ps2=mu2-mlp2
if(abs(ps2).gt.2) cycle
pt2=mup2-mlp2
if(abs(pt2).gt.2) cycle
z3=w3js(ju2,jl2,2,mu2,-mlp2,-ps2)
z4=w3js(ju2,jl2,2,mup2,-mlp2,-pt2)
z5=w3js(2,2,k2,-p2,pp2,q2)
z6=w3js(2,2,kp2,-ps2,pt2,q2)
z7=1.d0
if(mod(2*ju2-ml2-mlp2,4).ne.0) z7=-1.d0
zc(ml2,mlp2,mu2,mup2,k,kp,q)=z0*z1*z2*z3*z4*z5*z6*z7
enddo
enddo
enddo
enddo
end do
end do
end do
!$acc end kernels
END SUBROUTINE zcs
据我所知,我已经将相应的变量声明为私有,但我想我并不完全理解如何嵌套几个循环,和/或私有真正做什么。有什么建议可以帮助我正确理解发生的事情吗?
非常感谢, 的AdV
答案 0 :(得分:1)
这里的核心问题是你通过引用“w3js”例程传递循环边界变量“ju2”和“jl2”。这意味着循环跳闸计数可能在循环执行期间发生变化,从而阻止并行化。您可以尝试将这些变量设为私有,但最简单的方法是在w3js的参数上添加“VALUE”属性,以便按值传入它们。
请注意,它适用于“内核”情况,因为编译器只是并行化外部循环。在“并行”的情况下,你试图并行化这些“不可数”的内部循环。