【问题标题】:I cannot get !$acc parallel to work (but acc kernels does)我无法让 !$acc 并行工作(但 acc 内核可以)
【发布时间】:2018-04-17 03:00:24
【问题描述】:

我一直在尝试通过简单的代码使用 OpenACC,但我想我并不完全了解如何编写嵌套 OpenACC 循环或 private 做什么。我试图并行化的例程是:

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  

事实上,代码表现良好,如果我在调用此例程后比较 zc 矩阵,非 OpenACC 和 OpenACC 版本都会给出相同的答案。但是,如果我尝试使用并行指令来执行此操作,则似乎存在竞争条件,我无法弄清楚它在哪里。相关的变化只是:

!$acc parallel                                                                                                                                                                                
!$acc loop private(k,kp,k2,km,kp2,z0,q,q2)                                                                                                                                                    
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                                                                                                                     
         !$acc loop private(mu2,ml2,p2,z1,mup2,pp2,z2,mlp2,ps2,pt2,z3,z4,z5,z6,z7)                                                                                                            
         do mu2=-ju2,ju2,2                                                                                            


 [...]

!$acc end parallel  

据我所知,我已将适当的变量声明为私有,但我想我并不完全了解如何嵌套多个循环和/或私有的真正作用。有什么建议可以帮助我正确理解正在发生的事情吗?

非常感谢, 广告

【问题讨论】:

    标签: openacc


    【解决方案1】:

    这里的核心问题是您通过引用“w3js”例程来传递循环边界变量“ju2”和“jl2”。这意味着循环行程计数可能会在循环执行期间发生变化,从而阻止并行化。您可以尝试将这些变量设为私有,但最简单的做法是在 w3js 的参数上添加“VALUE”属性,以便按值传递它们。

    请注意,它适用于“内核”情况,因为编译器仅并行化外部循环。在“并行”情况下,您尝试并行化这些“不可数”内部循环。

    【讨论】:

      猜你喜欢
      • 2020-05-14
      • 2022-10-24
      • 1970-01-01
      • 2018-11-03
      • 2015-06-19
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多