There’s two ways to fix this.
First, remove “pA” from the declare create, then add it to a “present” clause. Since A and pA point to the same host address, when the compiler performs the present check, it will associate pA to the A’s device copy.
% cat test.f90
module Vars
real(8), pointer :: pA(:)
real(8), allocatable, target :: A(:)
!$acc declare create(A)
end module Vars
program foo
use Vars
allocate(A(3))
pA => A
!$acc serial present(pA)
pA(3) = 3.0
pA(1) = 1.0
!$acc end serial
!$acc update host(A)
print *, A
deallocate(A)
end program foo
% nvfortran -acc test.f90 ; a.out
1.000000000000000 0.000000000000000 3.000000000000000
The problem with this solution is if you need pA in a declare create in order to support directly accessing the variable from within a device routines. In this case, keep pA in the declare create but then call acc_attach to update the device copy of pA to point to the device copy of A.
% cat test2.F90
module Vars
real(8), pointer :: pA(:)
real(8), allocatable, target :: A(:)
!$acc declare create(A,pA)
contains
subroutine setVal(idx,val)
!$acc routine seq
integer, value :: idx
real(8), value :: val
pA(idx)=val
end subroutine setVal
end module Vars
program foo
use Vars
#ifdef _OPENACC
use openacc
#endif
allocate(A(3))
pA => A
#ifdef _OPENACC
call acc_attach(pA)
#endif
!$acc serial present(pA)
call setVal(3,3.0_8)
call setVal(1,1.0_8)
!$acc end serial
!$acc update host(A)
print *, A
deallocate(A)
end program foo
% nvfortran -acc test2.F90 ; a.out
1.000000000000000 0.000000000000000 3.000000000000000
Hope this helps,
Mat