question on !$acc declare and Fortran modules

Hello,

I need to port to OpenACC a code like this:

module storage_1
   integer, parameter :: N=1000
   real, dimension(:,:), allocatable :: A,B,C
end module storage_1 

subroutine allocate_1()
   use storage_1
   allocate(A(N,N),B(N,N),C(N,N))
   A = 1.  ; B = 2.  ; C = 0. 
end subroutine allocate_1

module storage_2
   integer, parameter :: N=1000
   real, dimension(:,:), allocatable :: A,B,C
end module storage_2 

subroutine allocate_2()
   use storage_2
   allocate(A(N,N),B(N,N),C(N,N))
   A = 2.  ; B = 3.  ; C = 0.
end subroutine allocate_2
   
subroutine matadd_sub_1()
   use storage_1; implicit none  
   integer :: i,j
!$acc kernels loop present(A,B,C)
   do i=1,N  
      do j=1,N  
         C(i,j) = A(i,j) + B(i,j)
      enddo      
   enddo     
!$acc end kernels 
end subroutine matadd_sub_1 

subroutine matadd_sub_2()  
   use storage_2; implicit none
   integer :: i,j
!$acc kernels loop present(A,B,C)
   do i=1,N  
      do j=1,N  
         C(i,j) = A(i,j) + B(i,j)
      enddo
   enddo     
!$acc end kernels 
end subroutine matadd_sub_2

subroutine print_1
   use storage_1; implicit none
   print*,"1: C: ",C(6,3)
end subroutine print_1

subroutine print_2
   use storage_2; implicit none
   print*,"2: C: ",C(6,3)
end subroutine print_2

program matadd 
   implicit none 
   call allocate_1  ;
   call allocate_2

!$acc data region create(???)
!$acc update device(???)
   call matadd_sub_1
   call matadd_sub_2
   !.... many other calls for 1 and 2.....
!$acc update host(???)
!$acc end data region

   call print_1
   call print_2

end program matadd

where I need to control CPU-GPU copies by means of update directives.

The problem is that I cannot specify the list of variables when declaring the data region because the main programm cannot see the storage variables which have the same names but are defined in different modules.

Maybe, the declare directive could help if the allocate subroutines become module subprograms of the corresponding storage modules, according to the standard (If my understanding is correct):

“If the directive appears in a Fortran MODULE subprogram, the associated region is the implicit region for the whole program”.

Is this feature implemented in PGI 12.5? I cannot have it working but maybe I am in a mistake.

Or the best would be to use declare directly in the storage modules but I think the standard does not allow for it. Is it?

I thank you very much for any help,

Francesco

Hi Francesco,

What you want to use here is the “declare device_resident” directive in your modules. However, as you noticed, “device_resident” is still under development so not available in 12.5.

In the meantime, you can use the PGI Accelerator “mirror” directive which does the same thing. For example:

 module storage_1
   integer, parameter :: N=1000
   real, dimension(:,:), allocatable :: A,B,C
!$acc mirror(A,B,C)
!acc declare device_resident(A,B,C)
end module storage_1

subroutine allocate_1()
   use storage_1
   allocate(A(N,N),B(N,N),C(N,N))
   A = 1.  ; B = 2.  ; C = 0.
!$acc update device(A,B)
end subroutine allocate_1

module storage_2
   integer, parameter :: N=1000
   real, dimension(:,:), allocatable :: A,B,C
!$acc mirror(A,B,C)
!acc declare device_resident(A,B,C)
end module storage_2

subroutine allocate_2()
   use storage_2
   allocate(A(N,N),B(N,N),C(N,N))
   A = 2.  ; B = 3.  ; C = 0.
!$acc update device(A,B)
end subroutine allocate_2
   
subroutine matadd_sub_1()
   use storage_1; implicit none 
   integer :: i,j
!$acc kernels loop 
   do i=1,N 
      do j=1,N 
         C(i,j) = A(i,j) + B(i,j)
      enddo     
   enddo     
!$acc end kernels
!$acc update host(C)
end subroutine matadd_sub_1

subroutine matadd_sub_2() 
   use storage_2; implicit none
   integer :: i,j
!$acc kernels loop 
   do i=1,N 
      do j=1,N 
         C(i,j) = A(i,j) + B(i,j)
      enddo
   enddo     
!$acc end kernels
!$acc update host(C)
end subroutine matadd_sub_2

subroutine print_1
   use storage_1; implicit none
   print*,"1: C: ",C(6,3)
end subroutine print_1

subroutine print_2
   use storage_2; implicit none
   print*,"2: C: ",C(6,3)
end subroutine print_2

program matadd
   implicit none

   call allocate_1  
   call allocate_2

   call matadd_sub_1
   call matadd_sub_2

   call print_1
   call print_2

end program matadd

Hope this helps,
Mat

Hi Mat,

It helps, thank you.

My code now uses mirror directives and works fine but I would like to use OpenACC. Reading the standard I cannot see how device_resident could help me (becase I need data also in the host), but your example starts clarifying it.

I wait for the new compiler version to test it

thanks again
Francesco