哪个 OpenACC 指令将告诉编译器仅在设备上执行语句?

Posted

技术标签:

【中文标题】哪个 OpenACC 指令将告诉编译器仅在设备上执行语句?【英文标题】:Which OpenACC directive will tell compiler to execute a statement on device only? 【发布时间】:2021-01-19 11:08:11 【问题描述】:

我正在学习使用 Fortran 的 OpenACC(使用 Nvidia 的一套工具),并通过将我的共轭梯度 (CG) 求解器的实现移植到 GPU 来做到这一点。

显然,我正在尝试使用以下命令在设备(GPU 内存)上保留尽可能多的数据:

27   ! Copy matrix (a_sparse), vectors (ax - b) and scalars (alpha - pap) to GPU                                     
28   !$acc enter data copyin(a_sparse)                                             
29   !$acc enter data copyin(a_sparse % row(:))                                    
30   !$acc enter data copyin(a_sparse % col(:))                                    
31   !$acc enter data copyin(a_sparse % val(:))                                    
32   !$acc enter data copyin(ax(:), ap(:), x(:), p(:), r(:), b(:))                                   
33   !$acc enter data copyin(alpha, beta, rho, rho_old, pap)                       

从那时起,构成 CG 求解器的求解算法的所有操作都通过 present 子句完成。对于 vector 操作,摘录如下:

49   !$acc  parallel loop      &                                                   
50   !$acc& present(r, b, ax)                                                      
51   do i = 1, n                                                                   
52     r(i) = b(i) - ax(i)                                                         
53   end do                                                                        

我用标量做同样的事情,例如:

87     !$acc kernels present(alpha, rho, pap)                                      
88     alpha = rho / pap                                                           
89     !$acc end kernels                                                           

所有标量变量都在设备上。在第 87-89 行中,我尝试仅在设备上执行命令 alpha = rho / pap,避免从主机传输任何数据或向主机传输任何数据,但 nsight-sys 分析器向我显示以下内容:

令我惊讶的是,第 87 行似乎有数据传输,在(红色“输入数据”方块)之前和之后(红色“退出数据”方块)计算构造(蓝色“Cg.f90:87”方块) )。

谁能告诉我这是怎么回事?第 87-89 行是否在设备上执行?此外,为什么这些“输入数据”和“退出数据”字段没有对应的 CUDA 命令?如果是这样,为什么主机和设备之间似乎有数据传输?如果没有,是否有一个 OpenACC 命令可以指示编译器仅在设备上执行一条不一定是循环的编程线?

我注意到数组操作也是如此,例如我在上面第 49-53 行中写的那些,那里也有一些数据传输,但我可以将其归因于应该传递给设备的变量 n .

【问题讨论】:

【参考方案1】:

它可以做一些事情。 Fortran 指定数组语法操作的右侧需要在赋值给左侧之前进行完全评估,因此编译器可能会分配一个临时数组来保存评估的结果。虽然编译器通常可以优化对临时的需求,但它可能是也可能不是问题。尝试将其设为显式循环,而不是使用数组语法来查看是否能解决问题。

第二种可能性是编译器需要复制数组描述符,因为它无法判断它们是否已更改。不过,我希望看到一些数据移动,而不仅仅是进入/退出区域。

第三种可能性是,这只是当前检查本身,它仍然调用进入/退出运行时调用。该调用不是复制数据,而是查找稍后传递给内核调用的设备指针,并且引用计数器递增/递减。

【讨论】:

以上是关于哪个 OpenACC 指令将告诉编译器仅在设备上执行语句?的主要内容,如果未能解决你的问题,请参考以下文章

在 openacc 中将 memcpy 用于设备阵列

在 OpenCL 上使用 OpenACC?

设备上的 OpenACC 重复数组

OpenACC + MPI Fortran 程序入门

OpenACC Hello World (win10)

谁能解释如何在 GCC 中使用 OpenACC?