GNU FORTRAN OpenACC访问设备上派生类型的可分配成员



我需要访问设备上派生类型的可分配成员。我在这里找到了一个很好的解决方案。但是,它使用PGI编译器。我不知道如何安装那个编译器,因为许可证有很多障碍。因此,我正在寻找一个GNU Fortran(Ubuntu 9.3.0-17ubuntu1~20.04(9.3.0的解决方案。

下面的示例程序在没有-fopenacc标志的情况下运行良好。然而,一旦该标志被启用,我就会得到以下错误:

libgomp: cuStreamSynchronize error: an illegal memory access was encountered

以下是我如何在没有OpenACC:的情况下运行代码(保存在名为:stackOverflow.f95的文件中(

$ gfortran -c stackOverflow.f95 
$ gfortran stackOverflow.o -o stackOverflow
$ ./stackOverflow 

以下是我如何使用OpenACC:运行代码

$ gfortran -fopenacc -c stackOverflow.f95 
$ gfortran -fopenacc stackOverflow.o -o stackOverflow
$ ./stackOverflow 

请看是否有解决方案?这是示例代码:

module modTest2
use openacc
implicit none

type :: Container
sequence
integer :: n
integer, allocatable :: arr(:)
end type Container
interface Container
procedure :: new_Container
end interface Container

contains
type(Container) function new_Container(n)
integer, intent(in) :: n

allocate(new_Container%arr(n))
end function new_Container
end module modTest2


program test2
use modTest2
implicit none

integer :: n, i
type(Container) :: c

print *, "Enter array size: "
read *, n  
print *, "Allocating..."
c = Container(n)
print *, "Allocation complete!"

print *, "Initializing..."
!$acc data copyin(c)
!$acc parallel loop present(c)
do i = 1, n
c%arr(i) = i*20
end do
!$acc end data
print *, "Initialization complete..."
do i = 1, n
print *, i, c%arr(i)
end do
end program test2

当前GCC将mixed component and non-component accesses诊断为!$acc data copyin(c) copyout(c%arr)以及!$acc enter data copyin(c) create(c%arr)!$acc exit data copyout(c%arr) delete(c),而不是Syntax error in OpenMP variable list。目前尚不清楚这是否意味着OpenACC的支持——我知道在条款处理顺序等方面存在尚未解决的问题,OpenACC技术委员会需要对此进行调查。(我也是该委员会的成员。(因此,PGI/NVHPC实际实现的可能不是标准的OpenACC。

也就是说,我能够使该程序与GCC/OpenACC一起工作,如下所示:将!$acc data copyin(c) copyout(c%arr)拆分为两个嵌套的数据区域:

!$acc data copyin(c) 
!$acc data copyout(c%arr)
[...]
!$acc end data
!$acc end data

或者,代替!$acc enter data copyin(c) create(c%arr)!$acc exit data copyout(c%arr) delete(c),将它们拆分为:

!$acc enter data copyin(c)
!$acc enter data create(c%arr)
[...]
!$acc exit data copyout(c%arr)
!$acc exit data delete(c)

对于这两种变体,我得到的结果与Mat上面发布的结果相同。

问题是您需要对"c%arr";。默认情况下,copy子句执行浅层复制。因此,用";副本(c(";,它正在复制"的主机地址;arr";其在设备上是不可访问的。

由于我在NVIDIA和NVHPC编译器团队(又名PGI(工作,我对gfortran没有深入了解,但假设以下代码也适用于他们。我更喜欢使用非结构化数据区域,因此包括结构化和非结构化版本。注意次序是重要的,因为";c";应该在"开始"之前在设备上创建;c%arr";因此编译器可以隐式地";附上";将其设置为";c"附上";基本上将设备指针填充到"0";arr";在";c";。颠倒顺序将要求代码通过";附上";条款或对";acc_attach";API

示例:

% cat test2.f90
module modTest2
use openacc
implicit none
type :: Container
sequence
integer :: n
integer, allocatable :: arr(:)
end type Container
interface Container
procedure :: new_Container
end interface Container
contains
type(Container) function new_Container(n)
integer, intent(in) :: n
allocate(new_Container%arr(n))
end function new_Container
end module modTest2
program test2
use modTest2
implicit none

integer :: n, i
type(Container) :: c

print *, "Enter array size: "
read *, n
print *, "Allocating..."
c = Container(n)
print *, "Allocation complete!"

print *, "Initializing..."
!acc enter data copyin(c) create(c%arr)
!$acc data copyin(c) copyout(c%arr)
!$acc parallel loop present(c)
do i = 1, n
c%arr(i) = i*20
end do
!$acc end data
!acc exit data copyout(c%arr) delete(c)
print *, "Initialization complete..."
do i = 1, n
print *, i, c%arr(i)
end do
end program test2
% nvfortran test2.f90 -acc; a.out
Enter array size:
1024
Allocating...
Allocation complete!
Initializing...
Initialization complete...
1           20
2           40
3           60
4           80
5          100
6          120
7          140
... cut ...
1020        20400
1021        20420
1022        20440
1023        20460
1024        20480

请注意,NVHPC SDK(包括编译器(是免费提供的。请参阅:https://developer.nvidia.com/hpc-sdk

最新更新