开放式加速器 | Fortran 90:并行化嵌套 DO 循环的最佳方法是啥?

Posted

技术标签:

【中文标题】开放式加速器 | Fortran 90:并行化嵌套 DO 循环的最佳方法是啥?【英文标题】:OpenACC | Fortran 90: What is the best way to parallelize nested DO loop?开放式加速器 | Fortran 90:并行化嵌套 DO 循环的最佳方法是什么? 【发布时间】:2021-10-01 21:34:33 【问题描述】:

我正在尝试使用 OpenACC 中的“Collapse”指令并行化以下嵌套 DO 循环结构(下面的第一个代码)。存在于最外层循环中的变量“nbl”存在于其他 DO 循环中,因此存在依赖性。感谢编译器,它提前显示了一个错误。所以我不得不妥协并只对剩下的四个最内层循环构建“折叠”指令。有没有办法通过利用“nbl = 1,nblocks”的并行性来并行化这个循环以获得最大性能?

编译器:pgfortran 标志:-acc -fast -ta=tesla:managed -Minfo=accel

由于最外层 DO 循环和其他内部 DO 循环之间的数据依赖性而导致错误的代码:

!$acc parallel loop collapse(5)
DO nbl = 1,nblocks
DO n_prim = 1,nprims
DO k = 1, NK(nbl)
DO j = 1, NJ(nbl)
DO i = 1, NI(nbl)

    Px(i,j,k,nbl,n_prim) = i*j + Cx(i,j,k,nbl,1)*Cx(i,j,k,nbl,5) + Cx(i,j,k,nbl,2)
    
ENDDO
ENDDO
ENDDO
ENDDO
ENDDO
!$acc end parallel loop

并行度较低的受损工作代码:

DO nbl = 1,nblocks
!$acc parallel loop collapse(4)
DO n_prim = 1,nprims
DO k = 1, NK(nbl)
DO j = 1, NJ(nbl)
DO i = 1, NI(nbl)

    Px(i,j,k,nbl,n_prim) = i*j + Cx(i,j,k,nbl,1)*Cx(i,j,k,nbl,5) + Cx(i,j,k,nbl,2)
    
ENDDO
ENDDO
ENDDO
ENDDO
!$acc end parallel loop
ENDDO

谢谢!

【问题讨论】:

ninjnk 看起来像什么? 你遇到了什么错误? 我不知道 openacc,但如果它遵循 openmp,由于您给出的原因,您将无法使用折叠结构。但是在 openacc 中,您可以将“acc 创建”和工作共享分开吗?如果是这样,您可以将整个循环放在设备上,但只需并行化内部循环,这可能足以获得良好的性能。 您也可以查看***.com/questions/28482833/…,这可能会有所帮助,但我目前无法直接看到。 NI = 300,NJ = 300,NK = 1 【参考方案1】:

依赖于循环上限的数组查找。为了折叠循环,在进入之前必须知道循环的迭代次数,但是这里的次数是可变的。

尝试以下方法并将并行度分为两个级别:

!$acc parallel loop collapse(2)
DO nbl = 1,nblocks
DO n_prim = 1,nprims
!$acc loop collapse(3)
DO k = 1, NK(nbl)
DO j = 1, NJ(nbl)
DO i = 1, NI(nbl)

【讨论】:

我还将在外循环上添加gang 子句(带有collapse(2) 的那个)和在内循环上添加vector 子句(collapse(3))以利用不同的OpenACC 提供的并行级别。 虽然不查看编译器反馈消息 (-Minfo=accel) 我无法确定,但编译器很可能隐式地将外部循环调度为“gang”,将内部循环调度为“vector” .我个人认为循环调度子句仅作为调优选项,所以尽量避免使用它们(除非我正在针对特定架构进行调优并且需要与默认不同的调度)。如果不同的架构更喜欢不同的时间表,这有助于性能可移植性,但它们肯定是有效的。

以上是关于开放式加速器 | Fortran 90:并行化嵌套 DO 循环的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

OpenACC + MPI Fortran 程序入门

无法并行化OpenACC循环

系统地并行化 fortran 2008 `do concurrent`,可能使用 openmp

如何使用CUDA并行化嵌套for循环以在2D数组上执行计算

混合组装和 Fortran 以及并行化 (OpenMP)

CUDA加速计算的基础C/C++