46 use,
intrinsic :: iso_c_binding, only : c_sizeof, c_int32_t, &
47 c_ptr, c_null_ptr, c_size_t, c_associated
53 integer,
allocatable :: ndofs(:)
54 integer,
allocatable :: offset(:)
56 type(c_ptr) :: reqs = c_null_ptr
57 type(c_ptr) :: buf_d = c_null_ptr
58 type(c_ptr) :: buf_v_d = c_null_ptr
59 type(c_ptr) :: dof_d = c_null_ptr
71 type(c_ptr),
allocatable :: stream(:)
72 type(c_ptr),
allocatable :: event(:)
74 type(c_ptr) :: send_event = c_null_ptr
89 subroutine hip_gs_pack(u_d, buf_d, dof_d, offset, n, stream) &
90 bind(c, name =
'hip_gs_pack')
91 use,
intrinsic :: iso_c_binding
93 integer(c_int),
value :: n, offset
94 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
100 bind(c, name =
'hip_gs_unpack')
101 use,
intrinsic :: iso_c_binding
103 integer(c_int),
value :: op, offset, n
104 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
110 bind(c, name =
'hip_gs_pack_vec')
111 use,
intrinsic :: iso_c_binding
113 integer(c_int),
value :: offset, n, nc, ns
114 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
120 stream) bind(c, name = 'hip_gs_unpack_vec')
121 use,
intrinsic :: iso_c_binding
123 integer(c_int),
value :: op, offset, n, nc, ns
124 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
129 subroutine cuda_gs_pack(u_d, buf_d, dof_d, offset, n, stream) &
130 bind(c, name =
'cuda_gs_pack')
131 use,
intrinsic :: iso_c_binding
133 integer(c_int),
value :: n, offset
134 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
139 subroutine cuda_gs_unpack(u_d, op, buf_d, dof_d, offset, n, stream) &
140 bind(c, name =
'cuda_gs_unpack')
141 use,
intrinsic :: iso_c_binding
143 integer(c_int),
value :: op, offset, n
144 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
150 bind(c, name =
'cuda_gs_pack_vec')
151 use,
intrinsic :: iso_c_binding
153 integer(c_int),
value :: offset, n, nc, ns
154 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
160 stream) bind(c, name = 'cuda_gs_unpack_vec')
161 use,
intrinsic :: iso_c_binding
163 integer(c_int),
value :: op, offset, n, nc, ns
164 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
171 bind(c, name =
'device_mpi_init_reqs')
172 use,
intrinsic :: iso_c_binding
174 integer(c_int),
value :: n
181 bind(c, name =
'device_mpi_free_reqs')
182 use,
intrinsic :: iso_c_binding
190 bind(c, name =
'device_mpi_isend')
191 use,
intrinsic :: iso_c_binding
193 integer(c_int),
value :: offset, nbytes, rank, tag, i
194 type(c_ptr),
value :: buf_d, reqs
200 bind(c, name =
'device_mpi_irecv')
201 use,
intrinsic :: iso_c_binding
203 integer(c_int),
value :: offset, nbytes, rank, tag, i
204 type(c_ptr),
value :: buf_d, reqs
210 bind(c, name =
'device_mpi_test')
211 use,
intrinsic :: iso_c_binding
213 integer(c_int),
value :: i
214 type(c_ptr),
value :: reqs
220 bind(c, name =
'device_mpi_waitall')
221 use,
intrinsic :: iso_c_binding
223 integer(c_int),
value :: n
224 type(c_ptr),
value :: reqs
230 bind(c, name =
'device_mpi_waitany')
231 use,
intrinsic :: iso_c_binding
233 integer(c_int),
value :: n
235 type(c_ptr),
value :: reqs
243 integer,
allocatable,
intent(inout) :: pe_order(:)
244 type(
stack_i4_t),
allocatable,
intent(inout) :: dof_stack(:)
245 logical,
intent(in) :: mark_dupes
246 integer,
allocatable :: dofs(:)
247 integer :: i, j, total
248 integer(c_size_t) :: sz
250 integer :: dupe, marked, k
251 real(c_rp) :: rp_dummy
252 integer(c_int32_t) :: i4_dummy
256 allocate(this%ndofs(
size(pe_order)))
257 allocate(this%offset(
size(pe_order)))
260 do i = 1,
size(pe_order)
261 this%ndofs(i) = dof_stack(pe_order(i))%size()
262 this%offset(i) = total
263 total = total + this%ndofs(i)
268 sz = c_sizeof(rp_dummy) * total
272 sz = c_sizeof(i4_dummy) * total
275 if (mark_dupes)
call doftable%init(2*total)
276 allocate(dofs(total))
280 do i = 1,
size(pe_order)
282 select type (arr => dof_stack(pe_order(i))%data)
284 do j = 1, this%ndofs(i)
285 k = this%offset(i) + j
287 if (doftable%get(arr(j), dupe) .eq. 0)
then
288 if (dofs(dupe) .gt. 0)
then
289 dofs(dupe) = -dofs(dupe)
295 call doftable%set(arr(j), k)
319 integer(c_size_t) :: sz
320 real(c_rp) :: rp_dummy
322 sz = c_sizeof(rp_dummy) *
gs_vec_nc * this%total
333 if (
allocated(this%ndofs))
deallocate(this%ndofs)
334 if (
allocated(this%offset))
deallocate(this%offset)
336 if (c_associated(this%buf_d))
call device_free(this%buf_d)
337 if (c_associated(this%buf_v_d))
call device_free(this%buf_v_d)
338 if (c_associated(this%dof_d))
call device_free(this%dof_d)
348 call this%init_order(send_pe, recv_pe)
350 call this%send_buf%init(this%send_pe, this%send_dof, .false.)
351 call this%recv_buf%init(this%recv_pe, this%recv_dof, .true.)
353#if defined(HAVE_HIP) || defined(HAVE_CUDA)
357 nstrm =
max(
size(this%send_pe),
size(this%recv_pe))
358 allocate(this%stream(nstrm))
364 allocate(this%event(nstrm))
373 this%vec_supported = .true.
374 this%vec_ready = .false.
385 call this%send_buf%init_vec()
386 call this%recv_buf%init_vec()
395 call this%send_buf%free()
396 call this%recv_buf%free()
397 this%vec_ready = .false.
399 call this%free_order()
400 call this%free_dofs()
402#if defined(HAVE_HIP) || defined(HAVE_CUDA)
403 if (
allocated(this%stream))
then
404 do i = 1,
size(this%stream)
407 deallocate(this%stream)
410 if (
allocated(this%event))
then
411 do i = 1,
size(this%event)
414 deallocate(this%event)
423 integer,
intent(in) :: n
424 real(kind=
rp),
dimension(n),
intent(inout) :: u
425 integer,
intent(in) :: tag
426 type(c_ptr),
intent(inout) :: deps
427 type(c_ptr),
intent(inout) :: strm
433 if (iand(this%nb_strtgy, 1) .eq. 0)
then
437 this%send_buf%buf_d, &
438 this%send_buf%dof_d, &
439 0, this%send_buf%total, &
443 this%send_buf%buf_d, &
444 this%send_buf%dof_d, &
445 0, this%send_buf%total, &
453 do i = 1,
size(this%send_pe)
455 rp*this%send_buf%offset(i), &
456 rp*this%send_buf%ndofs(i), this%send_pe(i), tag, &
457 this%send_buf%reqs, i)
462 do i = 1,
size(this%send_pe)
466 this%send_buf%buf_d, &
467 this%send_buf%dof_d, &
468 this%send_buf%offset(i), &
469 this%send_buf%ndofs(i), &
473 this%send_buf%buf_d, &
474 this%send_buf%dof_d, &
475 this%send_buf%offset(i), &
476 this%send_buf%ndofs(i), &
484 do i = 1,
size(this%send_pe)
487 rp*this%send_buf%offset(i), &
488 rp*this%send_buf%ndofs(i), this%send_pe(i), tag, &
489 this%send_buf%reqs, i)
498 integer,
intent(in) :: tag
501 do i = 1,
size(this%recv_pe)
503 rp*this%recv_buf%ndofs(i), this%recv_pe(i), tag, &
504 this%recv_buf%reqs, i)
512 integer,
intent(in) :: n
513 real(kind=
rp),
dimension(n),
intent(inout) :: u
514 type(c_ptr),
intent(inout) :: strm
515 integer :: op, done_req, i
520 if (iand(this%nb_strtgy, 2) .eq. 0)
then
525 this%recv_buf%buf_d, &
526 this%recv_buf%dof_d, &
527 0, this%recv_buf%total, &
531 this%recv_buf%buf_d, &
532 this%recv_buf%dof_d, &
533 0, this%recv_buf%total, &
547 this%recv_buf%reqs, done_req) .ne. 0)
551 this%recv_buf%buf_d, &
552 this%recv_buf%dof_d, &
553 this%recv_buf%offset(done_req), &
554 this%recv_buf%ndofs(done_req), &
555 this%stream(done_req))
558 this%recv_buf%buf_d, &
559 this%recv_buf%dof_d, &
560 this%recv_buf%offset(done_req), &
561 this%recv_buf%ndofs(done_req), &
562 this%stream(done_req))
572 do done_req = 1,
size(this%recv_pe)
574 this%event(done_req), 0)
586 integer,
intent(in) :: n, nc
587 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
588 integer,
intent(in) :: tag
589 type(c_ptr),
intent(inout) :: deps
590 type(c_ptr),
intent(inout) :: strm
597 call hip_gs_pack_vec(u_d, this%send_buf%buf_v_d, this%send_buf%dof_d, &
598 0, this%send_buf%total, nc, n, strm)
601 0, this%send_buf%total, nc, n, strm)
608 do i = 1,
size(this%send_pe)
610 rp*nc*this%send_buf%offset(i), &
611 rp*nc*this%send_buf%ndofs(i), this%send_pe(i), tag, &
612 this%send_buf%reqs, i)
620 integer,
intent(in) :: tag, nc
623 do i = 1,
size(this%recv_pe)
625 rp*nc*this%recv_buf%offset(i), &
626 rp*nc*this%recv_buf%ndofs(i), this%recv_pe(i), tag, &
627 this%recv_buf%reqs, i)
635 integer,
intent(in) :: n, nc
636 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
637 type(c_ptr),
intent(inout) :: strm
647 this%recv_buf%dof_d, 0, this%recv_buf%total, nc, n, strm)
650 this%recv_buf%dof_d, 0, this%recv_buf%total, nc, n, strm)
void cuda_gs_unpack(real *u_d, int op, real *buf_d, int *dof_d, int offset, int n, cudaStream_t stream)
void cuda_gs_pack(void *u_d, void *buf_d, void *dof_d, int offset, int n, cudaStream_t stream)
void cuda_gs_pack_vec(void *u_d, void *buf_d, void *dof_d, int offset, int n, int nc, int ns, cudaStream_t stream)
void cuda_gs_unpack_vec(real *u_d, int op, real *buf_d, int *dof_d, int offset, int n, int nc, int ns, cudaStream_t stream)
Return the device pointer for an associated Fortran array.
Copy data between host and device (or device and device)
Synchronize a device or stream.
integer, public pe_size
MPI size of communicator.
integer, public pe_rank
MPI rank.
Device abstraction, common interface for various accelerators.
subroutine, public device_event_record(event, stream)
Record a device event.
integer, parameter, public host_to_device
subroutine, public device_free(x_d)
Deallocate memory on the device.
subroutine, public device_event_destroy(event)
Destroy a device event.
subroutine, public device_alloc(x_d, s)
Allocate memory on the device.
subroutine, public device_stream_create_with_priority(stream, flags, prio)
Create a device stream/command queue with priority.
subroutine, public device_stream_wait_event(stream, event, flags)
Synchronize a device stream with an event.
subroutine, public device_event_create(event, flags)
Create a device event queue.
integer, public strm_high_prio
High priority stream setting.
subroutine, public device_memset(x_d, v, s, sync, strm)
Set memory on the device to a value.
subroutine, public device_stream_destroy(stream)
Destroy a device stream/command queue.
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 GPU aware MPI gather-scatter communication.
subroutine gs_device_mpi_nbsend_vec(this, u, n, nc, tag, deps, strm)
Fused nc-component send. u is the compact shared device buffer (component-outer, per-component stride...
subroutine gs_device_mpi_buf_init(this, pe_order, dof_stack, mark_dupes)
subroutine gs_device_mpi_init_vec(this)
Allocate the fused vector send and receive slabs in device memory, sized for GS_VEC_NC components....
subroutine gs_device_mpi_nbwait(this, u, n, op, strm)
Wait for non-blocking operations.
subroutine gs_device_mpi_free(this)
Deallocate MPI based communication method.
subroutine gs_device_mpi_nbrecv_vec(this, tag, nc)
Post non-blocking receives for a fused nc-component exchange.
subroutine gs_device_mpi_nbwait_vec(this, u, n, nc, op, strm)
Wait for a fused nc-component exchange and unpack/reduce into u.
subroutine gs_device_mpi_buf_free(this)
subroutine gs_device_mpi_nbsend(this, u, n, tag, deps, strm)
Post non-blocking send operations.
subroutine gs_device_mpi_buf_init_vec(this)
Allocate this buffer's fused vector slab, sized for up to GS_VEC_NC components. Deferred to the first...
subroutine gs_device_mpi_init(this, send_pe, recv_pe)
Initialise MPI based communication method.
subroutine gs_device_mpi_nbrecv(this, tag)
Post non-blocking receive operations.
Implements a hash table ADT.
integer, parameter, public c_rp
integer, parameter, public rp
Global precision used in computations.
Implements a dynamic stack ADT.
Gather-scatter communication method.
Buffers for non-blocking communication and packing/unpacking.
Gather-scatter communication using device MPI. The arrays are indexed per PE like send_pe and @ recv_...
Integer based hash table.