设备上的 OpenACC 重复数组

Posted

技术标签:

【中文标题】设备上的 OpenACC 重复数组【英文标题】:OpenACC duplicate array on device 【发布时间】:2021-11-12 03:11:18 【问题描述】:

在使用 OpenACC 加速的 Fortran 程序上,我需要在 GPU 上复制一个数组。复制的数组只会在 GPU 上使用,永远不会在主机上复制。我知道创建它的唯一方法是在主机上声明和分配它,然后acc data create它:

program test
    implicit none
    integer, parameter :: n = 1000
    real :: total
    real, allocatable :: array(:)
    real, allocatable :: array_d(:)

    allocate(array(n))
    allocate(array_d(n))

    array(:) = 1e0

    !$acc data copy(array) create(array_d) copyout(total)

    !$acc kernels
    array_d(:) = array(:)
    !$acc end kernels

    !$acc kernels
    total = sum(array_d)
    !$acc end kernels

    !$acc end data

    print *, sum(array)
    print *, total

    deallocate(array)
    deallocate(array_d)
end program

这是一个插图代码,因为所讨论的程序要复杂得多。

这个解决方案的问题是我必须allocate主机上的重复数组,即使我在这里不使用它。一些主机内存会被浪费,特别是对于大型阵列(即使我知道在主机内存用完之前我会用完设备内存)。在 CUDA Fortran 上,我知道我可以声明一个仅限设备的数组,但我不知道这是否可以通过 OpenACC 实现。

有没有更好的方法来执行此操作?

【问题讨论】:

【参考方案1】:

OpenACC 规范有“acc declare device_resident”,它分配一个您将使用的仅设备数组,而不是“数据创建”。比如:

    implicit none
    integer, parameter :: n = 1000
    real :: total
    real, allocatable :: array(:)
    real, allocatable :: array_d(:)
    !$acc declare device_resident(array_d)
    allocate(array(n))
    allocate(array_d(n))

    array(:) = 1e0

    !$acc data copy(array) copyout(total)

    !$acc kernels
    array_d(:) = array(:)
    !$acc end kernels

    !$acc kernels
    total = sum(array_d)
    !$acc end kernels

    !$acc end data

    print *, sum(array)
    print *, total

    deallocate(array)
    deallocate(array_d)
end program

尽管由于实现的复杂性和缺乏令人信服的用例,我们的编译器(NVHPC 又名 PGI)将 device_resident 视为创建,即仍然分配主机数组。因此,如果您使用的是 NVHPC 并且确实需要一个仅设备阵列,那么您需要在阵列上使用 CUDA Fortran“设备”属性。 CUDA Fortran 和 OpenACC 可以互操作,所以可以混合使用。

但是,对于绝大多数代码来说,浪费一点主机内存并不是问题,而且由于没有复制数据,因此不会影响性能。因此,如果您按原样保留代码,那应该不是问题。

【讨论】:

如何尝试提供“令人信服的用例”?我的一位合作者没有使用 openACC,因为主机阵列分配导致主机内存使用过多 我们的管理层使用多种因素来确定其他当前项目等功能的优先级,实施难度,如果请求者购买了支持,该功能的一般有用性,如果请求者被阻止并且不可行解决方法是可用的,以及其他因素。因此,我向您的合作者提出的第一个问题是,使用 CUDA Fortran“设备”属性是否足以解决问题?如果没有,那么我需要获取有关该项目的更多详细信息并将其提交给我们的管理层,我很乐意这样做。 我不确定 SO 是否有直接消息传递,但如果有,请随时与我联系。如果没有,并且您不介意在 NIVIDIA 的开发者论坛上注册,您可以在那里与我联系。我主持 NV HPC SDK 论坛:forums.developer.nvidia.com/c/accelerated-computing/… 我会和他聊天。出于可移植性的原因,我怀疑 CUDA Fortran 是否是可接受的替代方案,但这是他的电话,不是我的 - 该代码是众所周知的 HPC 电子结构应用程序。

以上是关于设备上的 OpenACC 重复数组的主要内容,如果未能解决你的问题,请参考以下文章

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

MPI+OpenACC编程中的GPU间通信

OpenACC 书上的范例代码(Jacobi 迭代),part 2

OpenACC nvlink 未定义类的引用

OpenACC 计算构建内的自定义函数

OpenACC:如何将 openacc pragma 应用于“宏循环”