40 use mpi_f08,
only : mpi_allreduce, mpi_alltoall, mpi_integer, mpi_max
48 use,
intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_loc, &
49 c_f_pointer, c_associated, c_sizeof, c_size_t, c_int64_t
56 integer,
allocatable :: ndofs(:)
58 integer,
allocatable :: offset(:)
61 integer,
allocatable :: remote_offset(:)
65 integer :: max_total = 0
67 type(c_ptr) :: buf_ptr = c_null_ptr
97 type(c_ptr) :: data_signals_ptr = c_null_ptr
101 type(c_ptr) :: ack_signals_ptr = c_null_ptr
106 integer(kind=i8) :: iter = 0
126 integer,
intent(in) :: pe_order(:)
127 type(
stack_i4_t),
intent(inout) :: dof_stack(0:)
128 integer :: i, ierr, n
129 integer(c_size_t) :: sz
130 real(c_rp) :: rp_dummy
131#ifndef HAVE_OPENSHMEM
132 call neko_error(
'Neko was not built with OpenSHMEM support')
137 allocate(this%ndofs(n))
138 allocate(this%offset(n))
139 allocate(this%remote_offset(n))
142 this%remote_offset(i) = -1
147 this%ndofs(i) = dof_stack(pe_order(i))%size()
148 this%offset(i) = this%total
149 this%total = this%total + this%ndofs(i)
154 call mpi_allreduce(this%total, this%max_total, 1, mpi_integer, mpi_max, &
160 sz = c_sizeof(rp_dummy) * int(
max(
gs_vec_nc*this%max_total, 1), c_size_t)
162 if (.not. c_associated(this%buf_ptr))
then
163 call neko_error(
'shmem_malloc failed for gs_shmem buffer')
172 if (
allocated(this%ndofs))
deallocate(this%ndofs)
173 if (
allocated(this%offset))
deallocate(this%offset)
174 if (
allocated(this%remote_offset))
deallocate(this%remote_offset)
177 if (c_associated(this%buf_ptr))
then
183 this%buf_ptr = c_null_ptr
195 integer(c_size_t) :: i64_size
196 integer(c_int64_t) :: i64_dummy
197 integer,
allocatable :: local_offsets(:), remote_offsets(:)
198#ifndef HAVE_OPENSHMEM
199 call neko_error(
'Neko was not built with OpenSHMEM support')
203 call this%init_order(send_pe, recv_pe)
205 call this%send_buf%init(this%send_pe, this%send_dof)
206 call this%recv_buf%init(this%recv_pe, this%recv_dof)
211 i64_size = c_sizeof(i64_dummy)
213 if (.not. c_associated(this%data_signals_ptr))
then
214 call neko_error(
'shmem_calloc failed for gs_shmem data signals')
217 if (.not. c_associated(this%ack_signals_ptr))
then
218 call neko_error(
'shmem_calloc failed for gs_shmem ack signals')
226 allocate(local_offsets(0:
pe_size - 1))
227 allocate(remote_offsets(0:
pe_size - 1))
229 do i = 1,
size(this%recv_pe)
230 local_offsets(this%recv_pe(i)) = this%recv_buf%offset(i)
232 call mpi_alltoall(local_offsets, 1, mpi_integer, &
233 remote_offsets, 1, mpi_integer,
neko_comm, ierr)
234 do i = 1,
size(this%send_pe)
235 this%send_buf%remote_offset(i) = remote_offsets(this%send_pe(i))
237 deallocate(local_offsets)
238 deallocate(remote_offsets)
241 this%vec_supported = .true.
258 if (c_associated(this%data_signals_ptr))
then
261 if (c_associated(this%ack_signals_ptr))
then
264 this%data_signals_ptr = c_null_ptr
265 this%ack_signals_ptr = c_null_ptr
269 call this%send_buf%free()
270 call this%recv_buf%free()
272 call this%free_order()
273 call this%free_dofs()
284 integer,
intent(in) :: n
285 real(kind=
rp),
dimension(n),
intent(inout) :: u
286 integer,
intent(in) :: tag
287 type(c_ptr),
intent(inout) :: deps
288 type(c_ptr),
intent(inout) :: strm
289 integer :: i, j, dst, base
290 integer(c_size_t) :: nbytes
291 integer ,
pointer :: sp(:)
292 real(kind=
rp),
pointer :: send_data(:), recv_data(:)
293 integer(c_int64_t),
pointer :: data_signals(:), ack_signals(:)
294 real(c_rp) :: rp_dummy
299 this%iter = this%iter + 1
301 call c_f_pointer(this%send_buf%buf_ptr, send_data, &
302 [
max(this%send_buf%max_total, 1)])
303 call c_f_pointer(this%recv_buf%buf_ptr, recv_data, &
304 [
max(this%recv_buf%max_total, 1)])
305 call c_f_pointer(this%data_signals_ptr, data_signals, [
pe_size])
306 call c_f_pointer(this%ack_signals_ptr, ack_signals, [
pe_size])
308 do i = 1,
size(this%send_pe)
309 dst = this%send_pe(i)
318 sp => this%send_dof(dst)%array()
319 base = this%send_buf%offset(i)
320 do concurrent(j = 1:this%send_dof(dst)%size())
321 send_data(base + j) = u(sp(j))
324 nbytes = int(this%send_buf%ndofs(i), c_size_t) * c_sizeof(rp_dummy)
327 c_loc(recv_data(this%send_buf%remote_offset(i) + 1)), &
328 c_loc(send_data(base + 1)), &
330 c_loc(data_signals(
pe_rank + 1)), &
339 integer,
intent(in) :: tag
348 integer,
intent(in) :: n
349 real(kind=
rp),
dimension(n),
intent(inout) :: u
350 type(c_ptr),
intent(inout) :: strm
352 integer :: i, j, src, base
353 integer(c_int64_t) :: dummy
354 integer ,
pointer ::
sp(:)
355 real(kind=
rp),
pointer :: recv_data(:)
356 integer(c_int64_t),
pointer :: data_signals(:), ack_signals(:)
359 call c_f_pointer(this%recv_buf%buf_ptr, recv_data, &
360 [
max(this%recv_buf%max_total, 1)])
361 call c_f_pointer(this%data_signals_ptr, data_signals, [
pe_size])
362 call c_f_pointer(this%ack_signals_ptr, ack_signals, [
pe_size])
364 do i = 1,
size(this%recv_pe)
365 src = this%recv_pe(i)
371 sp => this%recv_dof(src)%array()
372 base = this%recv_buf%offset(i)
376 do concurrent(j = 1:this%recv_dof(src)%size())
377 u(
sp(j)) = u(
sp(j)) + recv_data(base + j)
381 do concurrent(j = 1:this%recv_dof(src)%size())
382 u(
sp(j)) = u(
sp(j)) * recv_data(base + j)
386 do concurrent(j = 1:this%recv_dof(src)%size())
387 u(
sp(j)) = min(u(
sp(j)), recv_data(base + j))
391 do concurrent(j = 1:this%recv_dof(src)%size())
392 u(
sp(j)) =
max(u(
sp(j)), recv_data(base + j))
395 call neko_error(
"Unknown operation in gs_nbwait_shmem")
402 c_loc(ack_signals(
pe_rank + 1)), &
414 integer,
intent(in) :: n, nc
415 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
416 integer,
intent(in) :: tag
417 type(c_ptr),
intent(inout) :: deps
418 type(c_ptr),
intent(inout) :: strm
419 integer :: i, j, c, dst, base, ndst
420 integer(c_size_t) :: nbytes
421 integer,
pointer :: sp(:)
422 real(kind=
rp),
pointer :: send_data(:), recv_data(:)
423 integer(c_int64_t),
pointer :: data_signals(:), ack_signals(:)
424 real(c_rp) :: rp_dummy
427 this%iter = this%iter + 1
429 call c_f_pointer(this%send_buf%buf_ptr, send_data, &
430 [
max(nc*this%send_buf%max_total, 1)])
431 call c_f_pointer(this%recv_buf%buf_ptr, recv_data, &
432 [
max(nc*this%recv_buf%max_total, 1)])
433 call c_f_pointer(this%data_signals_ptr, data_signals, [
pe_size])
434 call c_f_pointer(this%ack_signals_ptr, ack_signals, [
pe_size])
436 do i = 1,
size(this%send_pe)
437 dst = this%send_pe(i)
442 sp => this%send_dof(dst)%array()
443 base = this%send_buf%offset(i)
444 ndst = this%send_buf%ndofs(i)
446 do concurrent(j = 1:ndst)
447 send_data(nc*base + (c-1)*ndst + j) = u((c-1)*n + sp(j))
451 nbytes = int(nc*ndst, c_size_t) * c_sizeof(rp_dummy)
453 c_loc(recv_data(nc*this%send_buf%remote_offset(i) + 1)), &
454 c_loc(send_data(nc*base + 1)), &
456 c_loc(data_signals(
pe_rank + 1)), &
465 integer,
intent(in) :: tag, nc
472 integer,
intent(in) :: n, nc
473 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
474 type(c_ptr),
intent(inout) :: strm
476 integer :: i, j, c, src, base, nsrc
477 integer(c_int64_t) :: dummy
478 integer,
pointer ::
sp(:)
479 real(kind=
rp),
pointer :: recv_data(:)
480 integer(c_int64_t),
pointer :: data_signals(:), ack_signals(:)
483 call c_f_pointer(this%recv_buf%buf_ptr, recv_data, &
484 [
max(nc*this%recv_buf%max_total, 1)])
485 call c_f_pointer(this%data_signals_ptr, data_signals, [
pe_size])
486 call c_f_pointer(this%ack_signals_ptr, ack_signals, [
pe_size])
488 do i = 1,
size(this%recv_pe)
489 src = this%recv_pe(i)
494 sp => this%recv_dof(src)%array()
495 base = this%recv_buf%offset(i)
496 nsrc = this%recv_buf%ndofs(i)
501 do concurrent(j = 1:nsrc)
502 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) + &
503 recv_data(nc*base + (c-1)*nsrc + j)
509 do concurrent(j = 1:nsrc)
510 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) * &
511 recv_data(nc*base + (c-1)*nsrc + j)
517 do concurrent(j = 1:nsrc)
518 u((c-1)*n +
sp(j)) = min(u((c-1)*n +
sp(j)), &
519 recv_data(nc*base + (c-1)*nsrc + j))
525 do concurrent(j = 1:nsrc)
526 u((c-1)*n +
sp(j)) =
max(u((c-1)*n +
sp(j)), &
527 recv_data(nc*base + (c-1)*nsrc + j))
531 call neko_error(
"Unknown operation in gs_shmem_nbwait_vec")
535 c_loc(ack_signals(
pe_rank + 1)), &
integer, public pe_size
MPI size of communicator.
integer, public pe_rank
MPI rank.
type(mpi_comm), public neko_comm
MPI communicator.
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...
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
Defines OpenSHMEM gather-scatter communication.
subroutine gs_shmem_buf_init(this, pe_order, dof_stack)
Allocate symmetric memory and per-neighbor bookkeeping for one direction of communication.
subroutine gs_shmem_nbrecv_vec(this, tag, nc)
No-op: receives are completed via remote put-with-signal.
subroutine gs_shmem_init(this, send_pe, recv_pe)
Initialise OpenSHMEM based communication method.
subroutine gs_shmem_nbwait_vec(this, u, n, nc, op, strm)
Fused nc-component wait/reduce: per peer, wait on the data signal and reduce nc component blocks into...
subroutine gs_shmem_nbsend(this, u, n, tag, deps, strm)
Pack the gathered shared dofs into the symmetric send buffer and issue non-blocking puts with signali...
subroutine gs_shmem_buf_free(this)
Release symmetric memory and bookkeeping.
subroutine gs_shmem_nbsend_vec(this, u, n, nc, tag, deps, strm)
Fused nc-component send: pack nc contiguous component blocks per peer slab and put nc*ndofs reals wit...
subroutine gs_shmem_free(this)
Deallocate OpenSHMEM based communication method.
subroutine gs_shmem_nbrecv(this, tag)
No-op: receives are completed via remote put-with-signal.
subroutine gs_shmem_nbwait(this, u, n, op, strm)
Wait per-neighbor for the signal indicating that data has landed, apply the gather-scatter operation ...
integer, parameter, public i8
integer, parameter, public sp
integer, parameter, public c_rp
integer, parameter, public rp
Global precision used in computations.
Fortran bindings to SHMEM's C API.
Implements a dynamic stack ADT.
Gather-scatter communication method.
Symmetric buffer for one direction of OpenSHMEM communication.
Gather-scatter communication using OpenSHMEM one-sided puts with per-rank signaling for completion (O...