Hello,
Here i am trying to parallelize my sequencial fortran code and offload to NVIDIA GPU with OpenACC (PGF90 compiler).
My code (test.f90) is written in following way-
Program main
use openacc
IMPLICIT NONE
// variable declarations
//blah blah
!$acc parallel loop
do i =1,1000
p(i) = a(i) + BESS(i*a(i))
enddo
!$acc end parallel
//blah blah
End Program main
Function BESS(x)
IMPLICIT NONE
REAL*8 x, BESS
BESS = SQRT(5)*(COS(x)*3-SIN(x)) // example
RETURN
END FUNCTION BESS
When i am trying to compile using below command -
pgf90 -acc test.f90
It giving me the following massage-
Procedures called in a compute region must have acc routine information: BESS (test.f90: 85)
Can someone help me to figure out this problem?
Hi aviggupta0123,
In order to call a routine within device code, there must be a device callable version available. To do this in OpenACC, you’ll need to decorate the routine with a “!$acc routine” directive so the compiler knows to create the device version. Something like:
Function BESS(x)
IMPLICIT NONE
!$acc routine
REAL*8 x, BESS
BESS = SQRT(5)*(COS(x)*3-SIN(x)) // example
RETURN
While this creates the device version of BESS, the compiler also needs to know at call site that there is a device version available. If BESS is in a module, the compiler has access to this information from the module prototype. However if the code is using F77 style API calling (as you show it in the example), you’ll also need to include a second routine directive in the same unit as the call.
IMPLICIT NONE
! variable declarations
! I assume you have something like so the compile knows BESS is a function
REAL*8 BESS
! add routine just after this
!$acc routine(BESS)
! code
!$acc parallel loop
do i =1,1000
p(i) = a(i) + BESS(i*a(i))
enddo
Hope this helps,
Mat
1 Like
Thank you! I found this answer very useful, especially adding the second directive
!$acc routine(BESS)
That resolved my problem.
One thing is puzzling me though, this directive resolves the error even in the absence of the first directive!$acc routine inside the routine (BESS here) 's implementation. Any comments on this?
You’re missing the link to the code so I can’t see it, but likely either “BESS” is getting inlined so no device routine is needed, or the compiler the compiler is auto-generating the device routine.
It can auto-create the device routine when it detects a routine is being called in device code and the definition of that routine is in the same scoping unit (in this case the same source file). We added this feature mostly for C++ for things like templates where the “routine” directive would be difficult to add.
Though to be standard compliant and since other compilers may not have this feature, I’d still recommend adding the explicit “routine” directive to the BESS itself.