Ambiguous interface with OpenACC device copy

Hello,

I have a puzzling behavior when calling an interface with OpenACC host_data construct, from a data region created with !$acc data [...] or !$acc enter data [...].
The Fortran code is compiled with PGI (v.21.5 aka nvfortran) ; the main program calls the following interface (minimal example):

! mod_interface.f90
MODULE mod_interface
  IMPLICIT NONE

    PUBLIC :: func

    INTERFACE func
            SUBROUTINE func_host(nd, arr1, arr2)
                    IMPLICIT NONE
                    INTEGER, INTENT(IN) :: nd
                    COMPLEX*16, INTENT(INOUT) :: arr1(:)
                    COMPLEX*16, INTENT(IN) :: arr2(:)
            END SUBROUTINE

            SUBROUTINE func_dev(nd, arr1, arr2)
                    USE cudafor
                    IMPLICIT NONE
                    INTEGER, INTENT(IN) :: nd
                    COMPLEX*16, DEVICE, INTENT(INOUT) :: arr1(:)
                    COMPLEX*16, INTENT(IN) :: arr2(:)
            END SUBROUTINE
    END INTERFACE

END MODULE mod_interface

In main.f90 both arr1 and arr2 are copied on device with OpenACC data directives, and the interface is called with the host_data use_device(arr1) construct to resolve the interface (minimal example):

! main.f90
PROGRAM main
  USE mod_interface
  IMPLICIT NONE

  INTEGER, PARAMETER :: nd=1000
  COMPLEX*16, ALLOCATABLE, DIMENSION(:) :: ahost
  COMPLEX*16, ALLOCATABLE, DIMENSION(:) :: adev

  ALLOCATE( ahost(nd), adev(nd) )

  !$acc data copyin(adev,ahost)
  !$acc host_data use_device(adev)
  CALL func(nd,adev,ahost)
  !$acc end host_data
  !$acc end data
END PROGRAM

I get an unexpected error message when compiling with pgf90 -acc -cuda -Minfo=accel mod_interface.f90 main.f90 :

NVFORTRAN-S-0155-Ambiguous interfaces for generic procedure func (main.f90: 13)
  0 inform,   0 warnings,   1 severes, 0 fatal for main

However, when using the enter data directive as in the following,

!main.f90
PROGRAM main
  USE mod_interface
  IMPLICIT NONE

  INTEGER, PARAMETER :: nd=1000
  COMPLEX*16, ALLOCATABLE, DIMENSION(:) :: ahost
  COMPLEX*16, ALLOCATABLE, DIMENSION(:) :: adev

  ALLOCATE( ahost(nd), adev(nd) )

  !$acc enter data copyin(adev,ahost)
  !$acc host_data use_device(adev)
  call func(nd,adev,ahost)
  !$acc end host_data
  !$acc exit data copyout(adev,ahost)

END PROGRAM

the code is compiled and executed without errors.

In both cases, I would expect that the host_data region tells the compiler to use the device copy of arr1, while the host copy of arr2 is taken as a default, even if it is present on device. According to this minimal example, this seems to be true only whitin an enter data / exit data construct. Which is the difference between the two data constructs, and how is it related to the ambiguity of the interface?

Thank you for your help,

Laura

Hi Laura,

While I’m not 100% sure, I think the use of the a host_data region within a structured data region should work as you have it. It appears the compiler is using the structured data region’s scope when matching the interface rather than the intended host_data region. Since an unstructured data region doesn’t have defined region within the code block, the scope of host_data region is being used in this case.

I’ve added an issue report, TPR #31128, and sent it to engineering for further review.

Thanks for the report,
Mat