Рутинный вектор OpenACC с аргументом intent out

#fortran #openacc #pgi-accelerator

#fortran #openacc #pgi-ускоритель

Вопрос:

В настоящее время я ускоряю код Fortran, где у меня есть основной ускоренный цикл в подпрограмме sub . В цикле я хочу вызвать подпрограмму subsub на устройстве с acc routine помощью . Подпрограмма имеет intent(out) аргумент val , который является закрытым в цикле. Как subsub и в самом цикле, я хочу использовать vector предложение:

 module calc
  implicit none
  public :: sub
  private
contains
  subroutine sub()
    integer :: i
    integer :: array(10)
    integer :: val
    !$acc kernels loop independent private(val)
    do i = 1, 10
      call subsub(val)
      array(i) = val
    enddo
    print "(10(i0, x))", array
  endsubroutine
  subroutine subsub(val)
    !$acc routine vector
    integer, intent(out) :: val
    integer :: i
    val = 0
    !$acc loop independent reduction( :val)
    do i = 1, 10
      val = val   1
    enddo
  endsubroutine
endmodule

program test                                               
  use calc, only: sub                                
  implicit none                                      
  call sub()                                         
endprogram                                                
 

При компиляции с помощью компилятора PGI версии 20.9-0 и запуске программы я получаю бессмысленные значения в переменной array . Когда я просто использую acc routine for subsub , я получаю правильное поведение (10 во всех значениях array ). Что не так в моем подходе к распараллеливанию этой подпрограммы?

Ответ №1:

Это похоже на проблему генерации кода компилятора в отношении того, как val обрабатывается в основном цикле. К счастью, обходной путь прост, просто добавьте установку val в основной цикл.

 % cat test.f90
module calc
  implicit none
  public :: sub
  private
contains
  subroutine sub()
    integer :: i
    integer :: array(10)
    integer :: val
    !$acc kernels loop independent private(val)
    do i = 1, 10
      val = 0
      call subsub(val)
      array(i) = val
    enddo
    print "(10(i0, x))", array
  endsubroutine
  subroutine subsub(val)
    !$acc routine vector
    integer, intent(out) :: val
    integer :: i
    val = 0
    !$acc loop independent reduction( :val)
    do i = 1, 10
      val = val   1
    enddo
  endsubroutine
endmodule

program test
  use calc, only: sub
  implicit none
  call sub()
endprogram
% nvfortran -acc -Minfo=accel test.f90 -V20.9 ; a.out
sub:
     10, Generating implicit copyout(array(:)) [if not already present]
     11, Loop is parallelizable
         Generating Tesla code
         11, !$acc loop gang ! blockidx%x
subsub:
     18, Generating Tesla code
         24, !$acc loop vector ! threadidx%x
             Generating reduction( :val)
             Vector barrier inserted for vector loop reduction
     24, Loop is parallelizable
10 10 10 10 10 10 10 10 10 10