Swapping arrays during time-stepping

A call to move_alloc with coarray arguments fall under image control statements (statements that affects the execution ordering between images).

From J3/24-007, 16.9.147, paragraph 5:

When a reference to MOVE_ALLOC is executed for which the FROM argument is a coarray, there is an implicit synchronization of all active images of the current team. On those images, execution of the segment (11.7.2) following the CALL statement is delayed until all other active images of the current team have executed the same statement the same number of times. When such a reference is executed, if any image of the current team has stopped or failed, an error condition occurs.

Imagine a 2-d stencil iteration in pseudo-code (may have errors :warning:):

real(dp), allocatable, codimension[*] :: f1(:,:), f2(:,:)
real(dp) :: residual, tol

! ... initialize ...

iterate: do
   call sweep(from=f1, to=f2)

   call fill_and_exchange_boundaries(f2)
   sync all

   residual = maxval(abs(f2 - f1))
   call co_max(residual)

   if (residual < tol) exit iterate

   swap: block
      real(dp), allocatable  tmp(:,:)[*]
      call move_alloc(f2,tmp) ! sync
      call move_alloc(f1,f2) ! sync
      call move_alloc(tmp,f1) ! sync
   end block swap

end do iterate

To avoid the synchronization which results from the symmetric memory of a coarray allocatable object, I suppose one has to do something like this instead (keep allocatable and codimension attributes separated):

type :: grid_t
    real, allocatable :: f1(:,:), f2(:,:)
end type

type(grid_t) :: grid[*]

iterate: do
   call sweep(grid%f1,grid%f2)
   call fill_boundaries(grid%f2)
   call exchange(grid)  ! exchange halo regions across images
   sync all

    if (...) exit iterate

   call swap(grid%f1, grid%f2)    ! uses `move_alloc` on local objects

end do iterate
2 Likes

No reason (matter of taste). I saw it done like this in some C++ code snippet and copied it here.

1 Like