pass a thread-specific variable to a subroutine implicitly

In my OpenMP project, I use a DO LOOP over a threaded subroutine “tool” and need to pass a single-variate function “func” as an input argument to the subroutine.

However, a tricky issue is that I have to let the single-variate function take one more argument and this argument is thread specific. In the sample code below, this thread specific variable is “i”.

With OpenMP, all I have to do is simply to add the directive “!$OMP THREADPRIVATE…” in the declaration area of a Module where the threaded subroutine and the single-variate function are defined (Please see the sample code below).

May I ask if there is a way with OpenACC to perform the same operation?

  1. main.f90

program main
use toolbox
integer :: j

a = [((j),j=1,9,2)]
b = [((j),j=2,10,2)]

!$OMP PARALLEL DO DEFAULT(SHARED)
do j=1,5
i=j
call tool(fun1,a(j),c(j))
enddo
!$OMP END PARALLEL DO
print*, 'output c array: ', c
end program main

  1. toolbox.f90

module toolbox
integer :: i
!$OMP THREADPRIVATE(i)
real :: a(5), b(5), c(5)
contains
subroutine tool(func,x1,y1)
interface
real function func(x)
real :: x
end function func
end interface
real :: x1,y1
y1=func(x1)
end subroutine tool

function func(x)
real :: func,x
func=x+b(i)
end function func
end module toolbox

Hi Bangbing,

May I ask if there is a way with OpenACC to perform the same operation?

Unfortunately there isn’t an equivalent way to perform this in OpenACC and you will instead need to pass “i” as an argument to “tool”.

Also, we don’t support passing function pointers.

Below is how I’d write this in OpenACC.

  • Mat
% cat test.f90
module toolbox
real :: a(5), b(5), c(5)
!$acc declare create(a,b,c)
contains
subroutine tool(x1,y1,i)
real :: x1,y1
integer, value :: i
!$acc routine seq
y1=func(x1,i)
end subroutine tool

function func(x,i)
real :: func,x
integer, value :: i
!$acc routine seq
func=x+b(i)
end function func
end module toolbox

program main
use toolbox
integer :: j,i

a = [((j),j=1,9,2)]
b = [((j),j=2,10,2)]
!$acc update device(a,b)
!$acc parallel loop
do j=1,5
i=j
call tool(a(j),c(j),i)
enddo
!$acc update host(c)
print*, 'output c array: ', c
end program main

% pgfortran test.f90 -acc -Minfo=accel; a.out
tool:
      5, Generating acc routine seq
func:
     12, Generating acc routine seq
main:
     26, Generating update device(b(:),a(:))
     27, Accelerator kernel generated
         Generating Tesla code
         28, !$acc loop gang, vector(5) ! blockidx%x threadidx%x
     32, Generating update host(c(:))
 output c array:     3.000000        7.000000        11.00000
    15.00000        19.00000