The complete host-memory migration: post the messages, copy the part of the window this rank already owns while they are in flight, then wait. This is the portable backend's whole implementation; the GPU backend calls PostOldWindowExchange / FinishOldWindowExchange itself so that it can serve the local part with a device-to-device copy instead.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(DomainDecomposition), | intent(in) | :: | decomp | |||
| integer, | intent(in) | :: | perElem | |||
| integer, | intent(in) | :: | nvar | |||
| integer, | intent(in) | :: | nLocalOld | |||
| real(kind=prec), | intent(in) | :: | uLocal(*) | |||
| integer, | intent(in) | :: | winFirst(1:decomp%nRanks) | |||
| integer, | intent(in) | :: | winLast(1:decomp%nRanks) | |||
| integer, | intent(in) | :: | wFirst | |||
| integer, | intent(in) | :: | wLast | |||
| real(kind=prec), | intent(inout) | :: | uWin(*) | |||
| integer(kind=int64), | intent(inout) | :: | nBytesRecv | |||
| integer(kind=int64), | intent(inout) | :: | nBytesSent | |||
| integer(kind=int64), | intent(inout) | :: | nElemRemote |
subroutine ExchangeOldWindowFlat(decomp,perElem,nvar,nLocalOld,uLocal,winFirst,winLast, &
wFirst,wLast,uWin,nBytesRecv,nBytesSent,nElemRemote)
!! The complete host-memory migration: post the messages, copy the part of the window this
!! rank already owns while they are in flight, then wait. This is the portable backend's whole
!! implementation; the GPU backend calls PostOldWindowExchange / FinishOldWindowExchange
!! itself so that it can serve the local part with a device-to-device copy instead.
implicit none
type(DomainDecomposition),intent(in) :: decomp
integer,intent(in) :: perElem
integer,intent(in) :: nvar
integer,intent(in) :: nLocalOld
real(prec),intent(in) :: uLocal(*)
integer,intent(in) :: winFirst(1:decomp%nRanks)
integer,intent(in) :: winLast(1:decomp%nRanks)
integer,intent(in) :: wFirst
integer,intent(in) :: wLast
real(prec),intent(inout) :: uWin(*)
integer(int64),intent(inout) :: nBytesRecv
integer(int64),intent(inout) :: nBytesSent
integer(int64),intent(inout) :: nElemRemote
! Local
integer :: a,b,e,iv,p,msgCount
integer :: myFirst,nWinElem
integer(int64) :: dst,src !! int64 for the reason given in PostOldWindowExchange
integer,allocatable :: requests(:)
myFirst = decomp%offsetElem(decomp%rankId+1)+1
nWinElem = max(wLast-wFirst+1,0)
allocate(requests(1:2*nvar*decomp%nRanks))
msgCount = 0
call PostOldWindowExchange(decomp,perElem,nvar,nLocalOld,uLocal,winFirst,winLast, &
wFirst,wLast,uWin,requests,msgCount, &
nBytesRecv,nBytesSent,nElemRemote)
! The part of my window I already own, copied while the messages are in flight. Element order
! within a variable is the storage order of both buffers, so this is a pure byte move and the
! migrated window is bit-identical to the v1 allgathered field.
call OwnedRun(decomp%offsetElem,decomp%rankId+1,wFirst,wLast,a,b)
do iv = 1,nvar
do e = a,b
dst = int(perElem,int64)*(int(e-wFirst,int64)+int(nWinElem,int64)*(iv-1))
src = int(perElem,int64)*(int(e-myFirst,int64)+int(nLocalOld,int64)*(iv-1))
do p = 1,perElem
uWin(dst+p) = uLocal(src+p)
enddo
enddo
enddo
call FinishOldWindowExchange(requests,msgCount)
deallocate(requests)
endsubroutine ExchangeOldWindowFlat