Move every packed message: one isend + irecv per non-self peer
with a non-empty message, the self pair as a local copy, then
waitall. Collective over the north rank row.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| logical, | intent(in), | optional | :: | device_resident |
|
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| type(comm_t), | private | :: | comm | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | n_r | ||||
| integer, | private | :: | n_s | ||||
| integer, | private | :: | nreq | ||||
| integer, | private | :: | o | ||||
| logical, | private | :: | on_device | ||||
| integer, | private | :: | p |
subroutine ocean_fold_exchange(device_resident) !! Move every packed message: one isend + irecv per non-self peer !! with a non-empty message, the self pair as a local copy, then !! `waitall`. Collective over the north rank row. logical, intent(in), optional :: device_resident !! `.false.` ⇒ host buffers; default device-resident. integer :: p, n_s, n_r, o, nreq, i logical :: on_device type(comm_t) :: comm if (.not. fx_active) return if (.not. fx_open .or. fx_sent) then error stop "rdb_ocean_fold_exchange: ocean_fold_exchange outside an open, unsent group" end if on_device = .true. if (present(device_resident)) on_device = device_resident comm = comm_env_compute_comm() nreq = 0 do p = 1, fx_npeer n_s = fx_poff(FOLD_FAM_T)*fx_sn(p, FOLD_FAM_T) + fx_poff(FOLD_FAM_U)*fx_sn(p, FOLD_FAM_U) n_r = fx_poff(FOLD_FAM_T)*fx_rn(p, FOLD_FAM_T) + fx_poff(FOLD_FAM_U)*fx_rn(p, FOLD_FAM_U) o = (p - 1)*fx_cap if (p == fx_self) then ! Self pair: the receive region is the send region (same list). if (on_device) then !$acc parallel loop present(fx_sbuf, fx_rbuf) do i = o + 1, o + n_s fx_rbuf(i) = fx_sbuf(i) end do else fx_rbuf(o + 1:o + n_s) = fx_sbuf(o + 1:o + n_s) end if cycle end if if (on_device) then !$acc host_data use_device(fx_sbuf, fx_rbuf) if (n_r > 0) then nreq = nreq + 1 call FOLD_IRECV_N(comm, fx_rbuf(o + 1:o + n_r), n_r, fx_peer_rank(p), & TAG_OC_FOLD, fx_reqs(nreq)) end if if (n_s > 0) then nreq = nreq + 1 call FOLD_ISEND_N(comm, fx_sbuf(o + 1:o + n_s), n_s, fx_peer_rank(p), & TAG_OC_FOLD, fx_reqs(nreq)) end if !$acc end host_data else if (n_r > 0) then nreq = nreq + 1 call FOLD_IRECV_N(comm, fx_rbuf(o + 1:o + n_r), n_r, fx_peer_rank(p), & TAG_OC_FOLD, fx_reqs(nreq)) end if if (n_s > 0) then nreq = nreq + 1 call FOLD_ISEND_N(comm, fx_sbuf(o + 1:o + n_s), n_s, fx_peer_rank(p), & TAG_OC_FOLD, fx_reqs(nreq)) end if end if end do if (nreq > 0) call waitall(fx_reqs(1:nreq), fx_stats(1:nreq)) fx_sent = .true. end subroutine ocean_fold_exchange