45 use,
intrinsic :: iso_c_binding, only : c_sizeof, c_int32_t, &
46 c_ptr, c_null_ptr, c_size_t, c_associated, c_int
53#if defined(HAVE_NCCL) || defined(HAVE_RCCL)
54 logical,
parameter,
public :: GS_DEVICE_NCCL_AVAIL = .true.
56 logical,
parameter,
public :: gs_device_nccl_avail = .false.
61 integer,
allocatable :: ndofs(:)
62 integer,
allocatable :: offset(:)
64 type(c_ptr) :: buf_d = c_null_ptr
65 type(c_ptr) :: buf_v_d = c_null_ptr
66 type(c_ptr) :: dof_d = c_null_ptr
78 type(c_ptr),
allocatable :: stream(:)
79 type(c_ptr),
allocatable :: event(:)
81 type(c_ptr) :: send_event = c_null_ptr
96 subroutine hip_gs_pack(u_d, buf_d, dof_d, offset, n, stream) &
97 bind(c, name =
'hip_gs_pack')
98 use,
intrinsic :: iso_c_binding
100 integer(c_int),
value :: n, offset
101 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
107 bind(c, name =
'hip_gs_unpack')
108 use,
intrinsic :: iso_c_binding
110 integer(c_int),
value :: op, offset, n
111 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
117 bind(c, name =
'hip_gs_pack_vec')
118 use,
intrinsic :: iso_c_binding
120 integer(c_int),
value :: offset, n, nc, ns
121 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
127 stream) bind(c, name = 'hip_gs_unpack_vec')
128 use,
intrinsic :: iso_c_binding
130 integer(c_int),
value :: op, offset, n, nc, ns
131 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
136 subroutine cuda_gs_pack(u_d, buf_d, dof_d, offset, n, stream) &
137 bind(c, name =
'cuda_gs_pack')
138 use,
intrinsic :: iso_c_binding
140 integer(c_int),
value :: n, offset
141 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
146 subroutine cuda_gs_unpack(u_d, op, buf_d, dof_d, offset, n, stream) &
147 bind(c, name =
'cuda_gs_unpack')
148 use,
intrinsic :: iso_c_binding
150 integer(c_int),
value :: op, offset, n
151 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
157 bind(c, name =
'cuda_gs_pack_vec')
158 use,
intrinsic :: iso_c_binding
160 integer(c_int),
value :: offset, n, nc, ns
161 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
167 stream) bind(c, name = 'cuda_gs_unpack_vec')
168 use,
intrinsic :: iso_c_binding
170 integer(c_int),
value :: op, offset, n, nc, ns
171 type(c_ptr),
value :: u_d, buf_d, dof_d, stream
178 rbuf_d, roffset, rcount, rrank, nbytes, stream) &
179 bind(c, name =
'device_nccl_sendrecv')
180 use,
intrinsic :: iso_c_binding
182 integer(c_int),
value :: soffset, scount, roffset, rcount
183 integer(c_int),
value :: srank, rrank, nbytes
184 type(c_ptr),
value :: sbuf_d, rbuf_d, stream
192 integer,
allocatable,
intent(inout) :: pe_order(:)
193 type(
stack_i4_t),
allocatable,
intent(inout) :: dof_stack(:)
194 logical,
intent(in) :: mark_dupes
195 integer,
allocatable :: dofs(:)
196 integer :: i, j, total
197 integer(c_size_t) :: sz
199 integer :: dupe, marked, k
200 real(c_rp) :: rp_dummy
201 integer(c_int32_t) :: i4_dummy
204 allocate(this%ndofs(
size(pe_order)))
205 allocate(this%offset(
size(pe_order)))
208 do i = 1,
size(pe_order)
209 this%ndofs(i) = dof_stack(pe_order(i))%size()
210 this%offset(i) = total
211 total = total + this%ndofs(i)
216 sz = c_sizeof(rp_dummy) * total
219 sz = c_sizeof(i4_dummy) * total
222 if (mark_dupes)
call doftable%init(2*total)
223 allocate(dofs(total))
227 do i = 1,
size(pe_order)
229 select type (arr => dof_stack(pe_order(i))%data)
231 do j = 1, this%ndofs(i)
232 k = this%offset(i) + j
234 if (doftable%get(arr(j), dupe) .eq. 0)
then
235 if (dofs(dupe) .gt. 0)
then
236 dofs(dupe) = -dofs(dupe)
242 call doftable%set(arr(j), k)
263 integer(c_size_t) :: sz
264 real(c_rp) :: rp_dummy
266 sz = c_sizeof(rp_dummy) *
gs_vec_nc * this%total
274 if (
allocated(this%ndofs))
deallocate(this%ndofs)
275 if (
allocated(this%offset))
deallocate(this%offset)
277 if (c_associated(this%buf_d))
call device_free(this%buf_d)
278 if (c_associated(this%buf_v_d))
call device_free(this%buf_v_d)
279 if (c_associated(this%dof_d))
call device_free(this%dof_d)
289#if !defined(HAVE_NCCL) && !defined(HAVE_RCCL)
290 call neko_error(
'Neko was not built with NCCL support')
293 call this%init_order(send_pe, recv_pe)
295 call this%send_buf%init(this%send_pe, this%send_dof, .false.)
296 call this%recv_buf%init(this%recv_pe, this%recv_dof, .true.)
298#if defined(HAVE_HIP) || defined(HAVE_CUDA)
302 nstrm =
max(
size(this%send_pe),
size(this%recv_pe))
303 allocate(this%stream(nstrm))
309 allocate(this%event(nstrm))
315 this%vec_supported = .true.
316 this%vec_ready = .false.
327 call this%send_buf%init_vec()
328 call this%recv_buf%init_vec()
337 call this%send_buf%free()
338 call this%recv_buf%free()
339 this%vec_ready = .false.
341 call this%free_order()
342 call this%free_dofs()
344#if defined(HAVE_HIP) || defined(HAVE_CUDA)
345 if (
allocated(this%stream))
then
346 do i = 1,
size(this%stream)
349 deallocate(this%stream)
352 if (
allocated(this%event))
then
353 do i = 1,
size(this%event)
356 deallocate(this%event)
365 integer,
intent(in) :: n
366 real(kind=
rp),
dimension(n),
intent(inout) :: u
367 integer,
intent(in) :: tag
368 type(c_ptr),
intent(inout) :: deps
369 type(c_ptr),
intent(inout) :: strm
375 do i = 1,
size(this%send_pe)
379 this%send_buf%buf_d, &
380 this%send_buf%dof_d, &
381 this%send_buf%offset(i), &
382 this%send_buf%ndofs(i), &
386 this%send_buf%buf_d, &
387 this%send_buf%dof_d, &
388 this%send_buf%offset(i), &
389 this%send_buf%ndofs(i), &
404 integer,
intent(in) :: tag
414 integer,
intent(in) :: n
415 real(kind=
rp),
dimension(n),
intent(inout) :: u
416 type(c_ptr),
intent(inout) :: strm
417 integer :: op, done_req, i
419 real(c_rp) :: rp_dummy
420 integer(c_int) :: nbytes
423 nbytes = c_sizeof(rp_dummy)
425 do i = 1,
size(this%send_pe)
428 nbytes*this%send_buf%offset(i), &
429 this%send_buf%ndofs(i), &
431 this%recv_buf%buf_d, &
432 nbytes*this%recv_buf%offset(i), &
433 this%recv_buf%ndofs(i), &
440 this%recv_buf%buf_d, &
441 this%recv_buf%dof_d, &
442 this%recv_buf%offset(i), &
443 this%recv_buf%ndofs(i), &
447 this%recv_buf%buf_d, &
448 this%recv_buf%dof_d, &
449 this%recv_buf%offset(i), &
450 this%recv_buf%ndofs(i), &
459 do done_req = 1,
size(this%recv_pe)
461 this%event(done_req), 0)
471 integer,
intent(in) :: n, nc
472 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
473 integer,
intent(in) :: tag
474 type(c_ptr),
intent(inout) :: deps
475 type(c_ptr),
intent(inout) :: strm
481 do i = 1,
size(this%send_pe)
484 call hip_gs_pack_vec(u_d, this%send_buf%buf_v_d, this%send_buf%dof_d, &
485 this%send_buf%offset(i), this%send_buf%ndofs(i), nc, n, &
489 this%send_buf%offset(i), this%send_buf%ndofs(i), nc, n, &
501 integer,
intent(in) :: tag, nc
507 integer,
intent(in) :: n, nc
508 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
509 type(c_ptr),
intent(inout) :: strm
510 integer :: op, done_req, i
512 real(c_rp) :: rp_dummy
513 integer(c_int) :: nbytes
516 nbytes = c_sizeof(rp_dummy)
518 do i = 1,
size(this%send_pe)
521 nbytes*nc*this%send_buf%offset(i), &
522 nc*this%send_buf%ndofs(i), &
524 this%recv_buf%buf_v_d, &
525 nbytes*nc*this%recv_buf%offset(i), &
526 nc*this%recv_buf%ndofs(i), &
533 this%recv_buf%dof_d, this%recv_buf%offset(i), &
534 this%recv_buf%ndofs(i), nc, n, this%stream(i))
537 this%recv_buf%dof_d, this%recv_buf%offset(i), &
538 this%recv_buf%ndofs(i), nc, n, this%stream(i))
546 do done_req = 1,
size(this%recv_pe)
548 this%event(done_req), 0)
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)
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_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 NCCL based gather-scatter communication.
subroutine gs_device_nccl_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_nccl_nbrecv(this, tag)
Post non-blocking receive operations.
subroutine gs_device_nccl_init(this, send_pe, recv_pe)
Initialise NCCL based communication method.
subroutine gs_device_nccl_nbsend(this, u, n, tag, deps, strm)
Post non-blocking send operations.
subroutine gs_device_nccl_nbwait(this, u, n, op, strm)
Wait for non-blocking operations.
subroutine gs_device_nccl_buf_init(this, pe_order, dof_stack, mark_dupes)
subroutine gs_device_nccl_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_nccl_nbrecv_vec(this, tag, nc)
No-op: send/recv and unpack happen in nbwait_vec.
subroutine gs_device_nccl_nbwait_vec(this, u, n, nc, op, strm)
Fused nc-component send/recv + unpack.
subroutine gs_device_nccl_free(this)
Deallocate MPI based communication method.
subroutine gs_device_nccl_buf_free(this)
subroutine gs_device_nccl_init_vec(this)
Allocate the fused vector send and receive slabs in device memory, sized for GS_VEC_NC components....
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 NCCL The arrays are indexed per PE like send_pe and @ recv_pe.
Integer based hash table.