OpenACC 常量参数

OpenACC constant parameters

我想知道在 OpenACC 内核中处理常量的正确方法是什么。

例如,在下面的代码中

module vecaddmod

  implicit none

  integer, parameter :: n = 100000
  !$acc declare create(n)

contains
  subroutine vecaddgpu(r, a, b)
    real, dimension(:) :: r, a, b
    integer :: i
    !$acc update self(n)
    !$acc data present(n)
    !$acc kernels loop copyin(a(1:n),b(1:n)) copyout(r(1:n))
    do i = 1, n
       r(i) = a(i) + b(i)
    enddo
    !$acc end data
  end subroutine vecaddgpu
end module vecaddmod

program main
  use vecaddmod
  implicit none
  integer :: i, errs, argcount
  real, dimension(:), allocatable :: a, b, r, e
  character*10 :: arg1

  allocate( a(n), b(n), r(n), e(n) )
  do i = 1, n
     a(i) = i
     b(i) = 1000*i
  enddo
  ! compute on the GPU
  call vecaddgpu( r, a, b )
  ! compute on the host to compare
  do i = 1, n
     e(i) = a(i) + b(i)
  enddo
  ! compare results
  errs = 0
  do i = 1, n
     if( r(i) /= e(i) )then
        errs = errs + 1
     endif
  enddo
  print *, errs, ' errors found'
  if( errs ) call exit(errs)
end program main

n 在模块中被声明为 CPU 上的常量,并用作循环中的范围。 nvfortran 警告我 Constant or Parameter used in data clause。上面的例子是处理这个问题的正确方法吗?我可以利用 GPU 上的常量内存,这样我就不需要在每次内核启动时将它从 CPU 复制到 GPU 吗?

谢谢。

编译器会将参数替换为文字值,因此无需将它们放在数据区域中。

module vecaddmod

  implicit none

  integer, parameter :: n = 100000

contains
  subroutine vecaddgpu(r, a, b)
    real, dimension(:) :: r, a, b
    integer :: i
    !$acc kernels loop copyin(a(1:n),b(1:n)) copyout(r(1:n))
    do i = 1, n
       r(i) = a(i) + b(i)
    enddo
  end subroutine vecaddgpu
end module vecaddmod

...

% nvfortran -acc -Minfo=accel test.f90
vecaddgpu:
     11, Generating copyin(a(:100000)) << "n" is replaced with 100000
         Generating copyout(r(:100000)) 
         Generating copyin(b(:100000)) 
     12, Loop is parallelizable
         Generating Tesla code
         12, !$acc loop gang, vector(128) ! blockidx%x threadidx%x