39 use mpi_f08,
only : mpi_statuses_ignore, mpi_status, &
40 mpi_request, mpi_isend, mpi_irecv, mpi_testsome, mpi_testall, &
43 use,
intrinsic :: iso_c_binding
51 real(kind=
rp),
allocatable :: send_buf(:)
53 real(kind=
rp),
allocatable :: recv_buf(:)
55 integer,
allocatable :: send_len(:), recv_len(:)
57 integer,
allocatable :: send_offset(:), recv_offset(:)
59 type(mpi_request),
allocatable :: send_request(:), recv_request(:)
62 integer,
allocatable :: recv_indices(:)
63 type(mpi_status),
allocatable :: recv_statuses(:)
68 real(kind=
rp),
allocatable :: send_buf_v(:)
69 real(kind=
rp),
allocatable :: recv_buf_v(:)
88 class(
gs_mpi_t),
intent(inout) :: this
91 integer :: i, nsend, nrecv, send_total, recv_total
93 call this%init_order(send_pe, recv_pe)
95 nsend =
size(this%send_pe)
96 nrecv =
size(this%recv_pe)
98 allocate(this%send_len(nsend), this%send_offset(nsend))
99 allocate(this%send_request(nsend))
101 allocate(this%recv_len(nrecv), this%recv_offset(nrecv))
102 allocate(this%recv_request(nrecv))
103 allocate(this%recv_indices(nrecv), this%recv_statuses(nrecv))
107 this%send_len(i) = this%send_dof(this%send_pe(i))%size()
108 this%send_offset(i) = send_total
109 send_total = send_total + this%send_len(i)
111 allocate(this%send_buf(
max(1, send_total)))
115 this%recv_len(i) = this%recv_dof(this%recv_pe(i))%size()
116 this%recv_offset(i) = recv_total
117 recv_total = recv_total + this%recv_len(i)
119 allocate(this%recv_buf(
max(1, recv_total)))
121 this%vec_supported = .true.
122 this%vec_ready = .false.
129 class(
gs_mpi_t),
intent(inout) :: this
130 integer :: send_total, recv_total
132 send_total = sum(this%send_len)
133 recv_total = sum(this%recv_len)
142 class(
gs_mpi_t),
intent(inout) :: this
144 if (
allocated(this%send_buf))
then
145 deallocate(this%send_buf)
148 if (
allocated(this%recv_buf))
then
149 deallocate(this%recv_buf)
152 if (
allocated(this%send_len))
then
153 deallocate(this%send_len)
156 if (
allocated(this%recv_len))
then
157 deallocate(this%recv_len)
160 if (
allocated(this%send_offset))
then
161 deallocate(this%send_offset)
164 if (
allocated(this%recv_offset))
then
165 deallocate(this%recv_offset)
168 if (
allocated(this%send_request))
then
169 deallocate(this%send_request)
172 if (
allocated(this%recv_request))
then
173 deallocate(this%recv_request)
176 if (
allocated(this%recv_indices))
then
177 deallocate(this%recv_indices)
180 if (
allocated(this%recv_statuses))
then
181 deallocate(this%recv_statuses)
184 if (
allocated(this%send_buf_v))
then
185 deallocate(this%send_buf_v)
188 if (
allocated(this%recv_buf_v))
then
189 deallocate(this%recv_buf_v)
191 this%vec_ready = .false.
193 call this%free_order()
194 call this%free_dofs()
200 class(
gs_mpi_t),
intent(inout) :: this
201 integer,
intent(in) :: n
202 real(kind=
rp),
dimension(n),
intent(inout) :: u
203 integer,
intent(in) :: tag
204 type(c_ptr),
intent(inout) :: deps
205 type(c_ptr),
intent(inout) :: strm
206 integer :: i, j, ierr, dst, off, ndst
216 do i = 1,
size(this%send_pe)
217 dst = this%send_pe(i)
218 off = this%send_offset(i)
219 ndst = this%send_len(i)
220 select type (
sp => this%send_dof(dst)%data)
224 this%send_buf(off + j) = u(
sp(j))
229 call mpi_isend(this%send_buf(off + 1), ndst, &
237 do i = 1,
size(this%send_pe)
238 dst = this%send_pe(i)
239 off = this%send_offset(i)
240 ndst = this%send_len(i)
241 select type (
sp => this%send_dof(dst)%data)
245 this%send_buf(off + j) = u(
sp(j))
248 call mpi_isend(this%send_buf(off + 1), ndst, &
259 class(
gs_mpi_t),
intent(inout) :: this
260 integer,
intent(in) :: tag
261 integer :: i, ierr, off, nsrc
272 do i = 1,
size(this%recv_pe)
273 off = this%recv_offset(i)
274 nsrc = this%recv_len(i)
275 call mpi_irecv(this%recv_buf(off + 1), nsrc, &
283 do i = 1,
size(this%recv_pe)
284 off = this%recv_offset(i)
285 nsrc = this%recv_len(i)
286 call mpi_irecv(this%recv_buf(off + 1), nsrc, &
296 class(
gs_mpi_t),
intent(inout) :: this
297 integer,
intent(in) :: n
298 real(kind=
rp),
dimension(n),
intent(inout) :: u
299 type(c_ptr),
intent(inout) :: strm
300 integer :: i, j, k, src, off, nsrc, ierr
303 logical :: sends_done
307 nreqs =
size(this%recv_pe)
308 do while (nreqs .gt. 0)
310 call mpi_testsome(
size(this%recv_request), this%recv_request, &
311 this%ncompleted, this%recv_indices, this%recv_statuses, ierr)
314 do k = 1, this%ncompleted
315 i = this%recv_indices(k)
317 src = this%recv_pe(i)
318 off = this%recv_offset(i)
319 nsrc = this%recv_len(i)
320 select type (
sp => this%recv_dof(src)%data)
332 u(
sp(j)) = u(
sp(j)) + this%recv_buf(off + j)
343 u(
sp(j)) = u(
sp(j)) * this%recv_buf(off + j)
354 u(
sp(j)) = min(u(
sp(j)), this%recv_buf(off + j))
365 u(
sp(j)) =
max(u(
sp(j)), this%recv_buf(off + j))
369 call neko_error(
"Unknown operation in gs_nbwait_mpi")
373 nreqs = nreqs - this%ncompleted
381 if (
size(this%send_request) .gt. 0)
then
383 do while (.not. sends_done)
384 call mpi_testall(
size(this%send_request), this%send_request, &
385 sends_done, mpi_statuses_ignore, ierr)
398 class(
gs_mpi_t),
intent(inout) :: this
399 integer,
intent(in) :: n, nc
400 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
401 integer,
intent(in) :: tag
402 type(c_ptr),
intent(inout) :: deps
403 type(c_ptr),
intent(inout) :: strm
404 integer :: i, j, c, ierr, dst, off, ndst
407 do i = 1,
size(this%send_pe)
408 dst = this%send_pe(i)
409 off = this%send_offset(i)
410 ndst = this%send_len(i)
411 select type (
sp => this%send_dof(dst)%data)
416 this%send_buf_v(nc*off + (c-1)*ndst + j) = &
423 call mpi_isend(this%send_buf_v(nc*off + 1), nc*ndst, &
431 do i = 1,
size(this%send_pe)
432 dst = this%send_pe(i)
433 off = this%send_offset(i)
434 ndst = this%send_len(i)
435 select type (
sp => this%send_dof(dst)%data)
440 this%send_buf_v(nc*off + (c-1)*ndst + j) = &
445 call mpi_isend(this%send_buf_v(nc*off + 1), nc*ndst, &
456 class(
gs_mpi_t),
intent(inout) :: this
457 integer,
intent(in) :: tag, nc
458 integer :: i, ierr, off, nsrc
462 do i = 1,
size(this%recv_pe)
463 off = this%recv_offset(i)
464 nsrc = this%recv_len(i)
465 call mpi_irecv(this%recv_buf_v(nc*off + 1), nc*nsrc, &
473 do i = 1,
size(this%recv_pe)
474 off = this%recv_offset(i)
475 nsrc = this%recv_len(i)
476 call mpi_irecv(this%recv_buf_v(nc*off + 1), nc*nsrc, &
486 class(
gs_mpi_t),
intent(inout) :: this
487 integer,
intent(in) :: n, nc
488 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
489 type(c_ptr),
intent(inout) :: strm
490 integer :: i, j, c, k, src, off, nsrc, ierr
493 logical :: sends_done
495 nreqs =
size(this%recv_pe)
496 do while (nreqs .gt. 0)
498 call mpi_testsome(
size(this%recv_request), this%recv_request, &
499 this%ncompleted, this%recv_indices, this%recv_statuses, ierr)
502 do k = 1, this%ncompleted
503 i = this%recv_indices(k)
504 src = this%recv_pe(i)
505 off = this%recv_offset(i)
506 nsrc = this%recv_len(i)
507 select type (
sp => this%recv_dof(src)%data)
514 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) + &
515 this%recv_buf_v(nc*off + (c-1)*nsrc + j)
523 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) * &
524 this%recv_buf_v(nc*off + (c-1)*nsrc + j)
532 u((c-1)*n +
sp(j)) = min(u((c-1)*n +
sp(j)), &
533 this%recv_buf_v(nc*off + (c-1)*nsrc + j))
541 u((c-1)*n +
sp(j)) =
max(u((c-1)*n +
sp(j)), &
542 this%recv_buf_v(nc*off + (c-1)*nsrc + j))
547 call neko_error(
"Unknown operation in gs_nbwait_vec_mpi")
551 nreqs = nreqs - this%ncompleted
555 if (
size(this%send_request) .gt. 0)
then
557 do while (.not. sends_done)
558 call mpi_testall(
size(this%send_request), this%send_request, &
559 sends_done, mpi_statuses_ignore, ierr)
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
type(mpi_comm), public neko_comm
MPI communicator.
integer, public neko_mpi_thread_provided
Thread support provided by the MPI library.
Defines a gather-scatter communication method.
integer, parameter, public gs_vec_nc
Maximum number of components handled by the fused vector (multi-component) halo exchange used by gs_o...
integer, parameter, public gs_comm_mpigpu
integer, parameter, public gs_comm_mpi
Defines MPI gather-scatter communication.
subroutine gs_nbwait_vec_mpi(this, u, n, nc, op, strm)
Wait for a fused nc-component exchange and reduce each received slab.
subroutine gs_nbwait_mpi(this, u, n, op, strm)
Wait for non-blocking operations.
subroutine gs_mpi_init(this, send_pe, recv_pe)
Initialise MPI based communication method See gs_comm.f90 for details.
subroutine gs_mpi_free(this)
Deallocate MPI based communication method.
subroutine gs_nbrecv_vec_mpi(this, tag, nc)
Post non-blocking receives for a fused nc-component exchange.
subroutine gs_nbsend_vec_mpi(this, u, n, nc, tag, deps, strm)
Post non-blocking sends for a fused nc-component exchange.
subroutine gs_nbsend_mpi(this, u, n, tag, deps, strm)
Post non-blocking send operations.
subroutine gs_mpi_init_vec(this)
Allocate the fused vector exchange buffers, sized for GS_VEC_NC components. Deferred to the first fus...
subroutine gs_nbrecv_mpi(this, tag)
Post non-blocking receive operations.
Defines Gather-scatter operations.
integer, parameter, public gs_op_add
integer, parameter, public gs_op_max
integer, parameter, public gs_op_min
integer, parameter, public gs_op_mul
integer, parameter, public sp
integer, parameter, public rp
Global precision used in computations.
Implements a dynamic stack ADT.
Gather-scatter communication method.
Gather-scatter communication using MPI.