Hello,
I have problems using mirror and update directives.
- When arrays have manually specified bounds and/or loops involve only a part of arrays, we cannot achieve the correct results. We prepared a simple test code which does not work (main.f90). It seems that accelerated regions must span all the index range to make the code working. Is there a limitation in any directive in such sense?
module storage
implicit none
real,allocatable::A(:,:),B(:,:),C(:,:),D(:,:),E(:,:)
!$acc mirror (A,B,C,D,E)
end module
!=========================================================================
program test
use storage
implicit none
integer::i,j
integer::l = 20
integer::m = 15
real:: sum0
real:: sum1
real:: sum2
real:: sum3
real:: sum4
allocate(A(0:l+1,0:m+1),B(0:l+1,0:m+1))
allocate(C(0:l+1,0:m+1),D(0:l+1,0:m+1))
allocate(E(0:l+1,0:m+1))
! init
do j = 0,m+1
do i = 0,l+1
A(i,j) = -100.
enddo
enddo
do j = 1,m
do i = 1,l
A(i,j) = 0.
enddo
enddo
!
B = +101.; C = +102.; D = +103.; E = +104.;
!
sum0 = 0.
sum1 = 0.
sum2 = 0.
sum3 = 0.
sum4 = 0.
!
! loop 0 (reference)
do j = 1,m
do i = 1,l
sum0 = sum0 + A(i,j)
enddo
enddo
!
! loop 1
!$acc update device(A)
!$acc update device(B)
!$acc region
do j = 1,m
do i = 1,l
B(i,j) = A(i,j)
enddo
enddo
!$acc end region
!$acc update host(B)
!
! check 1
do j = 1,m
do i = 1,l
sum1 = sum1 + B(i,j)
enddo
enddo
!
! loop 2
!$acc update device(A(0:l+1,0:m+1))
!$acc update device(C)
!$acc region
do j = 1,m
do i = 1,l
C(i,j) = A(i,j)
enddo
enddo
!$acc end region
!$acc update host(C)
!
! check 2
do j = 1,m
do i = 1,l
sum2 = sum2 + C(i,j)
enddo
enddo
!
! loop 3
!$acc update device(A(1:l,1:m))
!$acc update device(D)
!$acc region
do j = 1,m
do i = 1,l
D(i,j) = A(i,j)
enddo
enddo
!$acc end region
!$acc update host(D)
!
! check 3
do j = 1,m
do i = 1,l
sum3 = sum3 + D(i,j)
enddo
enddo
!
! loop 4
!$acc update device(A(0:l+1,0:m+1))
!$acc update device(E)
!$acc region
do j = 0,m+1
do i = 0,l+1
E(i,j) = A(i,j)
enddo
enddo
!$acc end region
!$acc update host(E)
!
! check 4
do j = 1,m
do i = 1,l
sum4 = sum4 + E(i,j)
enddo
enddo
!
write(*,*) " Result = 0 is correct!!!!"
write(*,*) "check 0 =", sum0
write(*,*) "check 1 =", sum1
write(*,*) "check 2 =", sum2
write(*,*) "check 3 =", sum3
write(*,*) "check 4 =", sum4
do j = 0,m+1
do i = 0,l+1
write(11,'(2(i4,1x),4(f12.5,1x))') i, j, A(i,j),B(i,j),C(i,j),D(i,j)
enddo
enddo
!
end program test
- update directive (update device as far as I see, update host behaves differently) is eliminated by compiler when host mirrored variable is modified in a subroutine. an example should be here. where do I have to put the directive to make sure it is executed?
module storage
implicit none
real,allocatable::A(:,:),B(:,:)
!$acc mirror (A,B)
end module
!=========================================================================
subroutine alloc_init()
use storage
integer::i,j
integer::l = 20
integer::m = 15
allocate(A(1:l,1:m),B(1:l,1:m))
! init
do j = 1,m
do i = 1,l
A(i,j) = 2.
enddo
enddo
!
end subroutine alloc_init
subroutine do_something()
use storage
integer::i,j
integer::l = 20
integer::m = 15
real:: sum0
sum0 = 0.
!
! loop 0 (reference)
do j = 1,m
do i = 1,l
sum0 = sum0 + A(i,j)
enddo
enddo
!
! loop 1
!$acc region
do j = 1,m
do i = 1,l
B(i,j) = A(i,j)
enddo
enddo
!$acc end region
!$acc update host(B)
!
! check 1
do j = 1,m
do i = 1,l
sum1 = sum1 + B(i,j)
enddo
enddo
!
write(*,*) " Result = 0 is correct!!!!"
write(*,*) "check 0 =", sum0
write(*,*) "check 1 =", sum1
do j = 0,m+1
do i = 0,l+1
write(11,'(2(i4,1x),4(f12.5,1x))') i, j, A(i,j),B(i,j)
enddo
enddo
end subroutine do_something
program test
use storage
implicit none
!
call alloc_init()
!$acc update device(A)
!$acc update device(B)
!
call do_something()
!
end program test
I am using PGI11.3 and compiling with -ta:nvidia flag
thanks in advance,
Francesco