Referencing device variable in HOST_DATA region

Hello.

I want to know if the following syntax is legal.

!$ACC HOST_DATA USE_DEVICE(cuAxial)
Ax_atil => cuAxial%atil
Ax_ahat => cuAxial%ahat
!$ACC END HOST_DATA

Ax_atil, Ax_ahat are device pointers, and cuAxial and its elements reside in device.

Hi CNJ,

By “Ax_atil, Ax_ahat are device pointers”, I’m assuming you mean that these are Fortran pointers declared with the CUDA Fortran “device” attribute.

For “cuAxial”, I’m assuming that this is a host derived type who’s device copy is being managed via OpenACC data directives.

In this case, it’s not that the syntax is illegal, it that you’ll get a seg fault on the host if you try to do this. The problem being that you’ll be dereferencing the device address of “cuAxial” on the host when you access the data member. To fix, use the data members in the host_data clause rather than the type.

!$ACC HOST_DATA USE_DEVICE(cuAxial%atil, cuAxial%ahat) 
Ax_atil => cuAxial%atil 
Ax_ahat => cuAxial%ahat 
!$ACC END HOST_DATA

Since I hadn’t tried this code before, I decided to write-up a more complete example:

% cat test.f90

module m
 implicit none
 type dt
  integer, allocatable, dimension(:) :: i
  real, allocatable, dimension(:) :: r
 end type

end module m

program p
 use m
 implicit none
 type(dt), target :: a, b, c
 integer, pointer, dimension(:), device :: dev_i
 real, pointer, dimension(:), device :: dev_r

 integer :: i, n
 n = 32
 allocate( a%i(n), b%i(n), c%i(n))
 allocate( a%r(n), b%r(n), c%r(n))
 do i = 1,n
  a%r(i) = i
  a%i(i) = i
  b%r(i) = 1000*i
  b%i(i) = 1000*i
  c%r(i) = 0
  c%i(i) = 0
 enddo

!$acc enter data create(a,b,c)
!$acc enter data copyin(a%i(:), a%r(:))
!$acc enter data copyin(b%i(:), b%r(:))
!$acc enter data create(c%i(:), c%r(:))

!$acc host_data use_device(a%i,a%r)
dev_i =>  a%i
dev_r =>  a%r
!$acc end host_data

!$acc parallel loop present(b,c) deviceptr(dev_i,dev_r)
 do i = 1,n
    c%i(i) = dev_i(i) + b%i(i)
    c%r(i) = dev_r(i) + b%r(i)
 end do

!$acc exit data delete(a%i(:), a%r(:))
!$acc exit data delete(b%i(:), b%r(:))
!$acc exit data copyout(c%i(:), c%r(:))
!$acc exit data delete(a,b,c)

 print *, c%i(:)
 print *, c%r(:)


 deallocate(a%i,a%r)
 deallocate(b%i,b%r)
 deallocate(c%i,c%r)
end

% pgfortran -V16.10 -Minfo=accel -acc -Mcuda test.f90
p:
     31, Generating enter data create(a,b,c)
     32, Generating enter data copyin(a%i(:),a%r(:))
     33, Generating enter data copyin(b%i(:),b%r(:))
     34, Generating enter data create(c%i(:),c%r(:))
     41, Generating present(b,c)
         Accelerator kernel generated
         Generating Tesla code
         42, !$acc loop gang, vector(32) ! blockidx%x threadidx%x
     47, Generating exit data delete(a%i(:),a%r(:))
     48, Generating exit data delete(b%i(:),b%r(:))
     49, Generating exit data copyout(c%i(:),c%r(:))
     50, Generating exit data delete(a,b,c)
% a.out
         1001         2002         3003         4004         5005         6006
         7007         8008         9009        10010        11011        12012
        13013        14014        15015        16016        17017        18018
        19019        20020        21021        22022        23023        24024
        25025        26026        27027        28028        29029        30030
        31031        32032
    1001.000        2002.000        3003.000        4004.000
    5005.000        6006.000        7007.000        8008.000
    9009.000        10010.00        11011.00        12012.00
    13013.00        14014.00        15015.00        16016.00
    17017.00        18018.00        19019.00        20020.00
    21021.00        22022.00        23023.00        24024.00
    25025.00        26026.00        27027.00        28028.00
    29029.00        30030.00        31031.00        32032.00