Fortran-OpenACC 例程如何调用另一个 Fortran-OpenACC 例程?
How can a Fortran-OpenACC routine call another Fortran-OpenACC routine?
我目前正在尝试通过使用带有 PGI (15.10) 编译器的 OpenACC 将大部分例程移植到 GPGPU 来加速光谱元素流体求解器。源代码是用 OO-Fortran 编写的。该软件具有调用其他函数和子例程的子例程“层”。为了使用 openacc 将代码转移到 GPU,我首先尝试在每个需要移植的例程中放置“$acc routine”指令。在编译过程中,使用“pgf90 -acc -Minfo=accel”,我收到以下错误:
nvvmCompileProgram error: 9.
Error: /tmp/pgacc2lMnIf9lMqx8.gpu (146, 24): parse invalid forward reference to function 'innerroutine_' with wrong type!
PGF90-S-0155-Compiler failed to translate accelerator region (see -Minfo messages): Device compiler exited with error status code (Test.f90: 1)
可以使用以下简单的 fortran 程序重现同样的问题:
PROGRAM Test
IMPLICIT NONE
CONTAINS
SUBROUTINE OuterRoutine( sol, xF, N )
!$acc routine
IMPLICIT NONE
INTEGER :: N
REAL(KIND=8) :: sol(0:N,1:3)
REAL(KIND=8) :: xF(0:N,1:3)
! LOCAL
INTEGER :: i
DO i = 0, N
xF(i,1:3) = InnerRoutine( sol(i,1:3) )
ENDDO
END SUBROUTINE OuterRoutine
FUNCTION InnerRoutine( sol ) RESULT( xF )
!$acc routine
IMPLICIT NONE
REAL(KIND=8) :: sol(1:3)
REAL(KIND=8) :: xF(1:3)
xF(1) = sol(1)*sol(2)
xF(2) = sol(1)*sol(3)
xF(3) = sol(1)*sol(1)
END FUNCTION InnerRoutine
END PROGRAM Test
同样,使用“pgf90 -acc -Minfo=accel”编译上述程序会产生问题。
openacc 是否支持启用 acc 的例程调用其他启用 acc 的例程?
如果是这样,我做错了什么?
您正确使用了 OpenACC "routine" 指令。这里的问题是我们 (PGI) 还不支持将 "routine" 与数组值函数一起使用。问题是这种支持需要编译器创建一个临时数组来保存 return 值。这意味着每个线程都需要分配这个临时数组,从而导致严重的性能损失。更糟糕的是,如果是帮派或工人级别的例程,如何处理共享临时数组。
我们确实收到了对此功能的开放请求,但我们可能需要一段时间才能解决它。同时,您可以尝试内联例程吗?即用“-Minline”编译。
我目前正在尝试通过使用带有 PGI (15.10) 编译器的 OpenACC 将大部分例程移植到 GPGPU 来加速光谱元素流体求解器。源代码是用 OO-Fortran 编写的。该软件具有调用其他函数和子例程的子例程“层”。为了使用 openacc 将代码转移到 GPU,我首先尝试在每个需要移植的例程中放置“$acc routine”指令。在编译过程中,使用“pgf90 -acc -Minfo=accel”,我收到以下错误:
nvvmCompileProgram error: 9.
Error: /tmp/pgacc2lMnIf9lMqx8.gpu (146, 24): parse invalid forward reference to function 'innerroutine_' with wrong type!
PGF90-S-0155-Compiler failed to translate accelerator region (see -Minfo messages): Device compiler exited with error status code (Test.f90: 1)
可以使用以下简单的 fortran 程序重现同样的问题:
PROGRAM Test
IMPLICIT NONE
CONTAINS
SUBROUTINE OuterRoutine( sol, xF, N )
!$acc routine
IMPLICIT NONE
INTEGER :: N
REAL(KIND=8) :: sol(0:N,1:3)
REAL(KIND=8) :: xF(0:N,1:3)
! LOCAL
INTEGER :: i
DO i = 0, N
xF(i,1:3) = InnerRoutine( sol(i,1:3) )
ENDDO
END SUBROUTINE OuterRoutine
FUNCTION InnerRoutine( sol ) RESULT( xF )
!$acc routine
IMPLICIT NONE
REAL(KIND=8) :: sol(1:3)
REAL(KIND=8) :: xF(1:3)
xF(1) = sol(1)*sol(2)
xF(2) = sol(1)*sol(3)
xF(3) = sol(1)*sol(1)
END FUNCTION InnerRoutine
END PROGRAM Test
同样,使用“pgf90 -acc -Minfo=accel”编译上述程序会产生问题。
openacc 是否支持启用 acc 的例程调用其他启用 acc 的例程?
如果是这样,我做错了什么?
您正确使用了 OpenACC "routine" 指令。这里的问题是我们 (PGI) 还不支持将 "routine" 与数组值函数一起使用。问题是这种支持需要编译器创建一个临时数组来保存 return 值。这意味着每个线程都需要分配这个临时数组,从而导致严重的性能损失。更糟糕的是,如果是帮派或工人级别的例程,如何处理共享临时数组。
我们确实收到了对此功能的开放请求,但我们可能需要一段时间才能解决它。同时,您可以尝试内联例程吗?即用“-Minline”编译。