ACC routine needed in Do Concurrent and Pure Functions

I have been experimenting with the new ability to have pure functions in DO CONCURRENT loops. In my testing, I have found that it is necessary to have “!$acc routine (func) seq” in my pure functions for the code to compile. Does this mean “!$acc routine” is needed for a pure function in a DO CONCURRENT loop? I have included a code sample. The first code compiles correctly and runs, but once the “!$acc routine” is deleted (second code) the code will not compile. Both codes are compiled with -stdpar=gpu.

      module addTwo_interface
!$acc routine(addTwo) seq
      interface
        pure function addTwo (num)
          implicit none
          real, intent(in) :: num
          real, intent(out) :: addTwo
        end function addTwo
      end interface
      end module
c
c-----------------------------------------------------------------------
c
      program TEST

      implicit none
      real :: numbers(5,5)
      integer :: i,j
      integer, dimension(:,:), allocatable :: temp
      allocate(temp(5,5))
c      
      call set_data(numbers)
c
      do i=1,5
        print*, numbers(i,1)
      enddo

      end program
c
c-----------------------------------------------------------------------
c
      subroutine set_data(numbers)
        use addTwo_interface
        implicit none
        real :: numbers(5,5)
        integer :: i,j
        do concurrent (i=1:5,j=1:5)
           numbers(i,j) = addTwo(1.0)
        enddo
      end subroutine
c
c-----------------------------------------------------------------------
c
      pure function addTwo(num)
!$acc routine(addTwo) seq
        implicit none
        real, intent(in) :: num
        real, intent(out) :: addTwo
c
        addTwo = num+2.0
c
      end function

Second code :

      module addTwo_interface
      interface
        pure function addTwo (num)
          implicit none
          real, intent(in) :: num
          real, intent(out) :: addTwo
        end function addTwo
      end interface
      end module
c
c-----------------------------------------------------------------------
c
      program TEST

      implicit none
      real :: numbers(5,5)
      integer :: i,j
      integer, dimension(:,:), allocatable :: temp
      allocate(temp(5,5))
c      
      call set_data(numbers)
c
      do i=1,5
        print*, numbers(i,1)
      enddo

      end program
c
c-----------------------------------------------------------------------
c
      subroutine set_data(numbers)
        use addTwo_interface
        implicit none
        real :: numbers(5,5)
        integer :: i,j
        do concurrent (i=1:5,j=1:5)
           numbers(i,j) = addTwo(1.0)
        enddo
      end subroutine
c
c-----------------------------------------------------------------------
c
      pure function addTwo(num)
        implicit none
        real, intent(in) :: num
        real, intent(out) :: addTwo
c
        addTwo = num+2.0
c
      end function
  • Miko
1 Like

Hi Miko,

A pure function just guarantees that it has no side effects but as far as calling, it’s no different than any other function or routine. Given we don’t yet support auto generation of device subroutines with DO CONNCURRENT, it does mean that all functions need to use the OpenACC routine directive in order to create the device callable version.

However, pure functions are much easier for the compiler to inline, so one work around would be to add the “-Minline” flag during compilation. If in your full application the function is in a separate file, then you’d want to do a two pass compilation. First compile with “-Mextract=lib:” to create the inline library, and then a second compile with “-Minline=lib:” to have the compiler use this info to inline the function.

-Mat

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.