Fortran OpenACC使用函数指针调用设备上的函数



如何通过函数指针访问设备上的函数?

在下面的代码中,我试图使用函数指针init访问init0init1。如果在编译过程中未启用OpenACC,代码将按预期工作。但是,使用OpenACC编译时会失败。以下代码保存为stackOverflow2.f95:

module modTest2
use openacc
implicit none

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

interface Container
procedure :: new_Container
end interface 

abstract interface
integer function function_template (i)
integer, intent (in) :: i
end function function_template
end interface

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, x, i
type(Container) :: c
procedure(function_template), pointer :: init

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


print *, "Enter initialization type (x): "
read *, x
print *, "Initializing..."
select case (x)
case (0)
init => init0
case default
init => init1
end select
!$acc data copyin(c) copyout(c%arr)
!$acc parallel loop present(c)
do i = 1, n
c%arr(i) = init(i)
end do
!$acc end data
print *, "Initialization complete..."

do i = 1, n
print *, i, c%arr(i)
end do


contains

integer function init0(i)
!$acc routine
integer, intent(in) :: i
init0 = 10*i
end function init0

integer function init1(i)
!$acc routine
integer, intent(in) :: i
init1 = 20*i
end function init1
end program test2

在没有OpenACC:的情况下可以看到正确的输出

$ gfortran -c stackOverflow2.f95
$ gfortran stackOverflow2.o -o a.out
$ ./a.out
Enter array size: 
3
Allocating...
Allocation complete!
Enter initialization type (x): 
0
Initializing...
Initialization complete...
1          10
2          20
3          30

以下是OpenACC的错误输出(注意此处使用NVIDIA编译器(:

$ /opt/nvidia/hpc_sdk/Linux_x86_64/22.1/compilers/bin/nvfortran stackOverflow2.f95 -acc; ./a.out
Enter array size: 
3
Allocating...
Allocation complete!
Enter initialization type (x): 
0
Initializing...
Initialization complete...
1            0
2            0
3            0

很抱歉,设备上还不支持函数指针(以及C++虚拟函数(。添加编译器反馈标志(-Minfo=accel(,您将看到以下消息:

% nvfortran -acc -Minfo=accel test.f90
test2:
62, Generating copyout(c%arr(:)) [if not already present]
Generating copyin(c) [if not already present]
65, Accelerator restriction: Indirect function/procedure calls are not supported

问题是,间接函数需要一个设备跳转表和运行时动态链接,而这些链接目前不可用。虽然我没有时间表,但我们正在探索未来如何提供这种支持的选项。

gfortran-11与以下内容一起使用可以达到目的:

module modTest2
use openacc
implicit none

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

interface Container
procedure :: new_Container
end interface 

abstract interface
integer function function_template (i)
integer, intent (in) :: i
end function function_template
end interface

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, x, i
type(Container) :: c
procedure(function_template), pointer :: init

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


print *, "Enter initialization type (x): "
read *, x
print *, "Initializing..."
select case (x)
case (0)
init => init0
case default
init => init1
end select
!$acc enter data copyin(c)
!$acc enter data create(c%arr)
!$acc parallel loop present(c)
do i = 1, n
c%arr(i) = init(i)
end do
!$acc exit data copyout(c%arr)
!$acc exit data delete(c)
print *, "Initialization complete..."

do i = 1, n
print *, i, c%arr(i)
end do


contains

integer function init0(i)
!$acc routine
integer, intent(in) :: i
init0 = 10*i
end function init0

integer function init1(i)
!$acc routine
integer, intent(in) :: i
init1 = 20*i
end function init1
end program test2

这是输出:

$ gfortran-11 -fopenacc stackOverflow2.f95
$ gfortran-11 -fopenacc stackOverflow2.o -o stackOverflow2
$ ./stackOverflow2 
Enter array size: 
4
Allocating...
Allocation complete!
Enter initialization type (x): 
0
Initializing...
Initialization complete...
1          10
2          20
3          30
4          40
$ ./stackOverflow2 
Enter array size: 
4
Allocating...
Allocation complete!
Enter initialization type (x): 
9
Initializing...
Initialization complete...
1          20
2          40
3          60
4          80

最新更新