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(:)
87 class(
gs_mpi_t),
intent(inout) :: this
90 integer :: i, nsend, nrecv, send_total, recv_total
92 call this%init_order(send_pe, recv_pe)
94 nsend =
size(this%send_pe)
95 nrecv =
size(this%recv_pe)
97 allocate(this%send_len(nsend), this%send_offset(nsend))
98 allocate(this%send_request(nsend))
100 allocate(this%recv_len(nrecv), this%recv_offset(nrecv))
101 allocate(this%recv_request(nrecv))
102 allocate(this%recv_indices(nrecv), this%recv_statuses(nrecv))
106 this%send_len(i) = this%send_dof(this%send_pe(i))%size()
107 this%send_offset(i) = send_total
108 send_total = send_total + this%send_len(i)
110 allocate(this%send_buf(
max(1, send_total)))
114 this%recv_len(i) = this%recv_dof(this%recv_pe(i))%size()
115 this%recv_offset(i) = recv_total
116 recv_total = recv_total + this%recv_len(i)
118 allocate(this%recv_buf(
max(1, recv_total)))
123 this%vec_supported = .true.
129 class(
gs_mpi_t),
intent(inout) :: this
131 if (
allocated(this%send_buf))
then
132 deallocate(this%send_buf)
135 if (
allocated(this%recv_buf))
then
136 deallocate(this%recv_buf)
139 if (
allocated(this%send_len))
then
140 deallocate(this%send_len)
143 if (
allocated(this%recv_len))
then
144 deallocate(this%recv_len)
147 if (
allocated(this%send_offset))
then
148 deallocate(this%send_offset)
151 if (
allocated(this%recv_offset))
then
152 deallocate(this%recv_offset)
155 if (
allocated(this%send_request))
then
156 deallocate(this%send_request)
159 if (
allocated(this%recv_request))
then
160 deallocate(this%recv_request)
163 if (
allocated(this%recv_indices))
then
164 deallocate(this%recv_indices)
167 if (
allocated(this%recv_statuses))
then
168 deallocate(this%recv_statuses)
171 if (
allocated(this%send_buf_v))
then
172 deallocate(this%send_buf_v)
175 if (
allocated(this%recv_buf_v))
then
176 deallocate(this%recv_buf_v)
179 call this%free_order()
180 call this%free_dofs()
186 class(
gs_mpi_t),
intent(inout) :: this
187 integer,
intent(in) :: n
188 real(kind=
rp),
dimension(n),
intent(inout) :: u
189 integer,
intent(in) :: tag
190 type(c_ptr),
intent(inout) :: deps
191 type(c_ptr),
intent(inout) :: strm
192 integer :: i, j, ierr, dst, off, ndst
202 do i = 1,
size(this%send_pe)
203 dst = this%send_pe(i)
204 off = this%send_offset(i)
205 ndst = this%send_len(i)
206 select type (
sp => this%send_dof(dst)%data)
210 this%send_buf(off + j) = u(
sp(j))
215 call mpi_isend(this%send_buf(off + 1), ndst, &
223 do i = 1,
size(this%send_pe)
224 dst = this%send_pe(i)
225 off = this%send_offset(i)
226 ndst = this%send_len(i)
227 select type (
sp => this%send_dof(dst)%data)
231 this%send_buf(off + j) = u(
sp(j))
234 call mpi_isend(this%send_buf(off + 1), ndst, &
245 class(
gs_mpi_t),
intent(inout) :: this
246 integer,
intent(in) :: tag
247 integer :: i, ierr, off, nsrc
258 do i = 1,
size(this%recv_pe)
259 off = this%recv_offset(i)
260 nsrc = this%recv_len(i)
261 call mpi_irecv(this%recv_buf(off + 1), nsrc, &
269 do i = 1,
size(this%recv_pe)
270 off = this%recv_offset(i)
271 nsrc = this%recv_len(i)
272 call mpi_irecv(this%recv_buf(off + 1), nsrc, &
282 class(
gs_mpi_t),
intent(inout) :: this
283 integer,
intent(in) :: n
284 real(kind=
rp),
dimension(n),
intent(inout) :: u
285 type(c_ptr),
intent(inout) :: strm
286 integer :: i, j, k, src, off, nsrc, ierr
289 logical :: sends_done
293 nreqs =
size(this%recv_pe)
294 do while (nreqs .gt. 0)
296 call mpi_testsome(
size(this%recv_request), this%recv_request, &
297 this%ncompleted, this%recv_indices, this%recv_statuses, ierr)
300 do k = 1, this%ncompleted
301 i = this%recv_indices(k)
303 src = this%recv_pe(i)
304 off = this%recv_offset(i)
305 nsrc = this%recv_len(i)
306 select type (
sp => this%recv_dof(src)%data)
317 u(
sp(j)) = u(
sp(j)) + this%recv_buf(off + j)
327 u(
sp(j)) = u(
sp(j)) * this%recv_buf(off + j)
337 u(
sp(j)) = min(u(
sp(j)), this%recv_buf(off + j))
347 u(
sp(j)) =
max(u(
sp(j)), this%recv_buf(off + j))
351 call neko_error(
"Unknown operation in gs_nbwait_mpi")
355 nreqs = nreqs - this%ncompleted
363 if (
size(this%send_request) .gt. 0)
then
365 do while (.not. sends_done)
366 call mpi_testall(
size(this%send_request), this%send_request, &
367 sends_done, mpi_statuses_ignore, ierr)
380 class(
gs_mpi_t),
intent(inout) :: this
381 integer,
intent(in) :: n, nc
382 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
383 integer,
intent(in) :: tag
384 type(c_ptr),
intent(inout) :: deps
385 type(c_ptr),
intent(inout) :: strm
386 integer :: i, j, c, ierr, dst, off, ndst
389 do i = 1,
size(this%send_pe)
390 dst = this%send_pe(i)
391 off = this%send_offset(i)
392 ndst = this%send_len(i)
393 select type (
sp => this%send_dof(dst)%data)
398 this%send_buf_v(nc*off + (c-1)*ndst + j) = &
405 call mpi_isend(this%send_buf_v(nc*off + 1), nc*ndst, &
413 do i = 1,
size(this%send_pe)
414 dst = this%send_pe(i)
415 off = this%send_offset(i)
416 ndst = this%send_len(i)
417 select type (
sp => this%send_dof(dst)%data)
422 this%send_buf_v(nc*off + (c-1)*ndst + j) = &
427 call mpi_isend(this%send_buf_v(nc*off + 1), nc*ndst, &
438 class(
gs_mpi_t),
intent(inout) :: this
439 integer,
intent(in) :: tag, nc
440 integer :: i, ierr, off, nsrc
444 do i = 1,
size(this%recv_pe)
445 off = this%recv_offset(i)
446 nsrc = this%recv_len(i)
447 call mpi_irecv(this%recv_buf_v(nc*off + 1), nc*nsrc, &
455 do i = 1,
size(this%recv_pe)
456 off = this%recv_offset(i)
457 nsrc = this%recv_len(i)
458 call mpi_irecv(this%recv_buf_v(nc*off + 1), nc*nsrc, &
468 class(
gs_mpi_t),
intent(inout) :: this
469 integer,
intent(in) :: n, nc
470 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
471 type(c_ptr),
intent(inout) :: strm
472 integer :: i, j, c, k, src, off, nsrc, ierr
475 logical :: sends_done
477 nreqs =
size(this%recv_pe)
478 do while (nreqs .gt. 0)
480 call mpi_testsome(
size(this%recv_request), this%recv_request, &
481 this%ncompleted, this%recv_indices, this%recv_statuses, ierr)
484 do k = 1, this%ncompleted
485 i = this%recv_indices(k)
486 src = this%recv_pe(i)
487 off = this%recv_offset(i)
488 nsrc = this%recv_len(i)
489 select type (
sp => this%recv_dof(src)%data)
496 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) + &
497 this%recv_buf_v(nc*off + (c-1)*nsrc + j)
505 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) * &
506 this%recv_buf_v(nc*off + (c-1)*nsrc + j)
514 u((c-1)*n +
sp(j)) = min(u((c-1)*n +
sp(j)), &
515 this%recv_buf_v(nc*off + (c-1)*nsrc + j))
523 u((c-1)*n +
sp(j)) =
max(u((c-1)*n +
sp(j)), &
524 this%recv_buf_v(nc*off + (c-1)*nsrc + j))
529 call neko_error(
"Unknown operation in gs_nbwait_vec_mpi")
533 nreqs = nreqs - this%ncompleted
537 if (
size(this%send_request) .gt. 0)
then
539 do while (.not. sends_done)
540 call mpi_testall(
size(this%send_request), this%send_request, &
541 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_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.