Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
gs_device_nccl.F90
Go to the documentation of this file.
1! Copyright (c) 2025, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
35 use num_types, only : rp, c_rp
36 use gs_comm, only : gs_comm_t, gs_vec_nc
37 use stack, only : stack_i4_t
38 use comm, only : pe_size, pe_rank
39 use htable, only : htable_i4_t
44 use utils, only : neko_error
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
47 implicit none
48 private
49
53#if defined(HAVE_NCCL) || defined(HAVE_RCCL)
54 logical, parameter, public :: GS_DEVICE_NCCL_AVAIL = .true.
55#else
56 logical, parameter, public :: gs_device_nccl_avail = .false.
57#endif
58
60 type, private :: gs_device_nccl_buf_t
61 integer, allocatable :: ndofs(:)
62 integer, allocatable :: offset(:)
63 integer :: total
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
67 contains
68 procedure, pass(this) :: init => gs_device_nccl_buf_init
69 procedure, pass(this) :: init_vec => gs_device_nccl_buf_init_vec
70 procedure, pass(this) :: free => gs_device_nccl_buf_free
72
75 type, public, extends(gs_comm_t) :: gs_device_nccl_t
76 type(gs_device_nccl_buf_t) :: send_buf
77 type(gs_device_nccl_buf_t) :: recv_buf
78 type(c_ptr), allocatable :: stream(:)
79 type(c_ptr), allocatable :: event(:)
80 integer :: nb_strtgy
81 type(c_ptr) :: send_event = c_null_ptr
82 contains
83 procedure, pass(this) :: init => gs_device_nccl_init
84 procedure, pass(this) :: free => gs_device_nccl_free
85 procedure, pass(this) :: nbsend => gs_device_nccl_nbsend
86 procedure, pass(this) :: nbrecv => gs_device_nccl_nbrecv
87 procedure, pass(this) :: nbwait => gs_device_nccl_nbwait
88 procedure, pass(this) :: init_vec => gs_device_nccl_init_vec
89 procedure, pass(this) :: nbsend_vec => gs_device_nccl_nbsend_vec
90 procedure, pass(this) :: nbrecv_vec => gs_device_nccl_nbrecv_vec
91 procedure, pass(this) :: nbwait_vec => gs_device_nccl_nbwait_vec
92 end type gs_device_nccl_t
93
94#ifdef HAVE_HIP
95 interface
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
99 implicit none
100 integer(c_int), value :: n, offset
101 type(c_ptr), value :: u_d, buf_d, dof_d, stream
102 end subroutine hip_gs_pack
103 end interface
104
105 interface
106 subroutine hip_gs_unpack(u_d, op, buf_d, dof_d, offset, n, stream) &
107 bind(c, name = 'hip_gs_unpack')
108 use, intrinsic :: iso_c_binding
109 implicit none
110 integer(c_int), value :: op, offset, n
111 type(c_ptr), value :: u_d, buf_d, dof_d, stream
112 end subroutine hip_gs_unpack
113 end interface
114
115 interface
116 subroutine hip_gs_pack_vec(u_d, buf_d, dof_d, offset, n, nc, ns, stream) &
117 bind(c, name = 'hip_gs_pack_vec')
118 use, intrinsic :: iso_c_binding
119 implicit none
120 integer(c_int), value :: offset, n, nc, ns
121 type(c_ptr), value :: u_d, buf_d, dof_d, stream
122 end subroutine hip_gs_pack_vec
123 end interface
124
125 interface
126 subroutine hip_gs_unpack_vec(u_d, op, buf_d, dof_d, offset, n, nc, ns, &
127 stream) bind(c, name = 'hip_gs_unpack_vec')
128 use, intrinsic :: iso_c_binding
129 implicit none
130 integer(c_int), value :: op, offset, n, nc, ns
131 type(c_ptr), value :: u_d, buf_d, dof_d, stream
132 end subroutine hip_gs_unpack_vec
133 end interface
134#elif HAVE_CUDA
135 interface
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
139 implicit none
140 integer(c_int), value :: n, offset
141 type(c_ptr), value :: u_d, buf_d, dof_d, stream
142 end subroutine cuda_gs_pack
143 end interface
144
145 interface
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
149 implicit none
150 integer(c_int), value :: op, offset, n
151 type(c_ptr), value :: u_d, buf_d, dof_d, stream
152 end subroutine cuda_gs_unpack
153 end interface
154
155 interface
156 subroutine cuda_gs_pack_vec(u_d, buf_d, dof_d, offset, n, nc, ns, stream) &
157 bind(c, name = 'cuda_gs_pack_vec')
158 use, intrinsic :: iso_c_binding
159 implicit none
160 integer(c_int), value :: offset, n, nc, ns
161 type(c_ptr), value :: u_d, buf_d, dof_d, stream
162 end subroutine cuda_gs_pack_vec
163 end interface
164
165 interface
166 subroutine cuda_gs_unpack_vec(u_d, op, buf_d, dof_d, offset, n, nc, ns, &
167 stream) bind(c, name = 'cuda_gs_unpack_vec')
168 use, intrinsic :: iso_c_binding
169 implicit none
170 integer(c_int), value :: op, offset, n, nc, ns
171 type(c_ptr), value :: u_d, buf_d, dof_d, stream
172 end subroutine cuda_gs_unpack_vec
173 end interface
174#endif
175
176 interface
177 subroutine device_nccl_sendrecv(sbuf_d, soffset, scount, srank, &
178 rbuf_d, roffset, rcount, rrank, nbytes, stream) &
179 bind(c, name = 'device_nccl_sendrecv')
180 use, intrinsic :: iso_c_binding
181 implicit none
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
185 end subroutine device_nccl_sendrecv
186 end interface
187
188contains
189
190 subroutine gs_device_nccl_buf_init(this, pe_order, dof_stack, mark_dupes)
191 class(gs_device_nccl_buf_t), intent(inout) :: this
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
198 type(htable_i4_t) :: doftable
199 integer :: dupe, marked, k
200 real(c_rp) :: rp_dummy
201 integer(c_int32_t) :: i4_dummy
202
203
204 allocate(this%ndofs(size(pe_order)))
205 allocate(this%offset(size(pe_order)))
206
207 total = 0
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)
212 end do
213
214 this%total = total
215
216 sz = c_sizeof(rp_dummy) * total
217 call device_alloc(this%buf_d, sz)
218
219 sz = c_sizeof(i4_dummy) * total
220 call device_alloc(this%dof_d, sz)
221
222 if (mark_dupes) call doftable%init(2*total)
223 allocate(dofs(total))
224
225 ! Copy from dof_stack into dofs, optionally marking duplicates with doftable
226 marked = 0
227 do i = 1, size(pe_order)
228 ! %array() breaks on cray
229 select type (arr => dof_stack(pe_order(i))%data)
230 type is (integer)
231 do j = 1, this%ndofs(i)
232 k = this%offset(i) + j
233 if (mark_dupes) then
234 if (doftable%get(arr(j), dupe) .eq. 0) then
235 if (dofs(dupe) .gt. 0) then
236 dofs(dupe) = -dofs(dupe)
237 marked = marked + 1
238 end if
239 dofs(k) = -arr(j)
240 marked = marked + 1
241 else
242 call doftable%set(arr(j), k)
243 dofs(k) = arr(j)
244 end if
245 else
246 dofs(k) = arr(j)
247 end if
248 end do
249 end select
250 end do
251
252 call device_memcpy(dofs, this%dof_d, total, host_to_device, sync = .true.)
253
254 deallocate(dofs)
255 call doftable%free()
256
257 end subroutine gs_device_nccl_buf_init
258
262 class(gs_device_nccl_buf_t), intent(inout) :: this
263 integer(c_size_t) :: sz
264 real(c_rp) :: rp_dummy
265
266 sz = c_sizeof(rp_dummy) * gs_vec_nc * this%total
267 call device_alloc(this%buf_v_d, sz)
268
269 end subroutine gs_device_nccl_buf_init_vec
270
271 subroutine gs_device_nccl_buf_free(this)
272 class(gs_device_nccl_buf_t), intent(inout) :: this
273
274 if (allocated(this%ndofs)) deallocate(this%ndofs)
275 if (allocated(this%offset)) deallocate(this%offset)
276
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)
280 end subroutine gs_device_nccl_buf_free
281
283 subroutine gs_device_nccl_init(this, send_pe, recv_pe)
284 class(gs_device_nccl_t), intent(inout) :: this
285 type(stack_i4_t), intent(inout) :: send_pe
286 type(stack_i4_t), intent(inout) :: recv_pe
287 integer :: i, nstrm
288
289#if !defined(HAVE_NCCL) && !defined(HAVE_RCCL)
290 call neko_error('Neko was not built with NCCL support')
291#endif
292
293 call this%init_order(send_pe, recv_pe)
294
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.)
297
298#if defined(HAVE_HIP) || defined(HAVE_CUDA)
299 ! Create a set of non-blocking streams. The per-peer streams and events
300 ! are indexed over both send_pe (pack, sendrecv) and recv_pe (unpack,
301 ! sync), so size them for the larger of the two peer lists.
302 nstrm = max(size(this%send_pe), size(this%recv_pe))
303 allocate(this%stream(nstrm))
304 do i = 1, nstrm
305 call device_stream_create_with_priority(this%stream(i), 1, &
307 end do
308
309 allocate(this%event(nstrm))
310 do i = 1, nstrm
311 call device_event_create(this%event(i), 2)
312 end do
313#endif
314
315 this%vec_supported = .true.
316 this%vec_ready = .false.
317
318 end subroutine gs_device_nccl_init
319
324 subroutine gs_device_nccl_init_vec(this)
325 class(gs_device_nccl_t), intent(inout) :: this
326
327 call this%send_buf%init_vec()
328 call this%recv_buf%init_vec()
329
330 end subroutine gs_device_nccl_init_vec
331
333 subroutine gs_device_nccl_free(this)
334 class(gs_device_nccl_t), intent(inout) :: this
335 integer :: i
336
337 call this%send_buf%free()
338 call this%recv_buf%free()
339 this%vec_ready = .false.
340
341 call this%free_order()
342 call this%free_dofs()
343
344#if defined(HAVE_HIP) || defined(HAVE_CUDA)
345 if (allocated(this%stream)) then
346 do i = 1, size(this%stream)
347 call device_stream_destroy(this%stream(i))
348 end do
349 deallocate(this%stream)
350 end if
351
352 if (allocated(this%event)) then
353 do i = 1, size(this%event)
354 call device_event_destroy(this%event(i))
355 end do
356 deallocate(this%event)
357 end if
358#endif
359
360 end subroutine gs_device_nccl_free
361
363 subroutine gs_device_nccl_nbsend(this, u, n, tag, deps, strm)
364 class(gs_device_nccl_t), intent(inout) :: this
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
370 integer :: i
371 type(c_ptr) :: u_d
372
373 u_d = device_get_ptr(u)
374
375 do i = 1, size(this%send_pe)
376 call device_stream_wait_event(this%stream(i), deps, 0)
377#ifdef HAVE_HIP
378 call hip_gs_pack(u_d, &
379 this%send_buf%buf_d, &
380 this%send_buf%dof_d, &
381 this%send_buf%offset(i), &
382 this%send_buf%ndofs(i), &
383 this%stream(i))
384#elif HAVE_CUDA
385 call cuda_gs_pack(u_d, &
386 this%send_buf%buf_d, &
387 this%send_buf%dof_d, &
388 this%send_buf%offset(i), &
389 this%send_buf%ndofs(i), &
390 this%stream(i))
391#else
392 call neko_error('gs_device_nccl: no backend')
393#endif
394 end do
395
396
397 ! Everything else is done in the wait routine
398
399 end subroutine gs_device_nccl_nbsend
400
402 subroutine gs_device_nccl_nbrecv(this, tag)
403 class(gs_device_nccl_t), intent(inout) :: this
404 integer, intent(in) :: tag
405 integer :: i
406
407 ! Everything is done in the wait routine
408
409 end subroutine gs_device_nccl_nbrecv
410
412 subroutine gs_device_nccl_nbwait(this, u, n, op, strm)
413 class(gs_device_nccl_t), intent(inout) :: this
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
418 type(c_ptr) :: u_d
419 real(c_rp) :: rp_dummy
420 integer(c_int) :: nbytes
421
422 u_d = device_get_ptr(u)
423 nbytes = c_sizeof(rp_dummy)
424
425 do i = 1, size(this%send_pe)
426
427 call device_nccl_sendrecv(this%send_buf%buf_d, &
428 nbytes*this%send_buf%offset(i), &
429 this%send_buf%ndofs(i), &
430 this%send_pe(i), &
431 this%recv_buf%buf_d, &
432 nbytes*this%recv_buf%offset(i), &
433 this%recv_buf%ndofs(i), &
434 this%recv_pe(i), &
435 nbytes, &
436 this%stream(i))
437
438#ifdef HAVE_HIP
439 call hip_gs_unpack(u_d, op, &
440 this%recv_buf%buf_d, &
441 this%recv_buf%dof_d, &
442 this%recv_buf%offset(i), &
443 this%recv_buf%ndofs(i), &
444 this%stream(i))
445#elif HAVE_CUDA
446 call cuda_gs_unpack(u_d, op, &
447 this%recv_buf%buf_d, &
448 this%recv_buf%dof_d, &
449 this%recv_buf%offset(i), &
450 this%recv_buf%ndofs(i), &
451 this%stream(i))
452#else
453 call neko_error('gs_device_mpi: no backend')
454#endif
455 call device_event_record(this%event(i), this%stream(i))
456 end do
457
458 ! Sync non-blocking streams
459 do done_req = 1, size(this%recv_pe)
460 call device_stream_wait_event(strm, &
461 this%event(done_req), 0)
462 end do
463
464 end subroutine gs_device_nccl_nbwait
465
469 subroutine gs_device_nccl_nbsend_vec(this, u, n, nc, tag, deps, strm)
470 class(gs_device_nccl_t), intent(inout) :: this
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
476 integer :: i
477 type(c_ptr) :: u_d
478
479 u_d = device_get_ptr(u)
480
481 do i = 1, size(this%send_pe)
482 call device_stream_wait_event(this%stream(i), deps, 0)
483#ifdef HAVE_HIP
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, &
486 this%stream(i))
487#elif HAVE_CUDA
488 call cuda_gs_pack_vec(u_d, this%send_buf%buf_v_d, this%send_buf%dof_d, &
489 this%send_buf%offset(i), this%send_buf%ndofs(i), nc, n, &
490 this%stream(i))
491#else
492 call neko_error('gs_device_nccl: no backend')
493#endif
494 end do
495
496 end subroutine gs_device_nccl_nbsend_vec
497
499 subroutine gs_device_nccl_nbrecv_vec(this, tag, nc)
500 class(gs_device_nccl_t), intent(inout) :: this
501 integer, intent(in) :: tag, nc
502 end subroutine gs_device_nccl_nbrecv_vec
503
505 subroutine gs_device_nccl_nbwait_vec(this, u, n, nc, op, strm)
506 class(gs_device_nccl_t), intent(inout) :: this
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
511 type(c_ptr) :: u_d
512 real(c_rp) :: rp_dummy
513 integer(c_int) :: nbytes
514
515 u_d = device_get_ptr(u)
516 nbytes = c_sizeof(rp_dummy)
517
518 do i = 1, size(this%send_pe)
519
520 call device_nccl_sendrecv(this%send_buf%buf_v_d, &
521 nbytes*nc*this%send_buf%offset(i), &
522 nc*this%send_buf%ndofs(i), &
523 this%send_pe(i), &
524 this%recv_buf%buf_v_d, &
525 nbytes*nc*this%recv_buf%offset(i), &
526 nc*this%recv_buf%ndofs(i), &
527 this%recv_pe(i), &
528 nbytes, &
529 this%stream(i))
530
531#ifdef HAVE_HIP
532 call hip_gs_unpack_vec(u_d, op, this%recv_buf%buf_v_d, &
533 this%recv_buf%dof_d, this%recv_buf%offset(i), &
534 this%recv_buf%ndofs(i), nc, n, this%stream(i))
535#elif HAVE_CUDA
536 call cuda_gs_unpack_vec(u_d, op, this%recv_buf%buf_v_d, &
537 this%recv_buf%dof_d, this%recv_buf%offset(i), &
538 this%recv_buf%ndofs(i), nc, n, this%stream(i))
539#else
540 call neko_error('gs_device_nccl: no backend')
541#endif
542 call device_event_record(this%event(i), this%stream(i))
543 end do
544
545 ! Sync non-blocking streams
546 do done_req = 1, size(this%recv_pe)
547 call device_stream_wait_event(strm, &
548 this%event(done_req), 0)
549 end do
550
551 end subroutine gs_device_nccl_nbwait_vec
552
553end module gs_device_nccl
void cuda_gs_unpack(real *u_d, int op, real *buf_d, int *dof_d, int offset, int n, cudaStream_t stream)
Definition gs.cu:132
void cuda_gs_pack(void *u_d, void *buf_d, void *dof_d, int offset, int n, cudaStream_t stream)
Definition gs.cu:116
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)
Definition gs.cu:166
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)
Definition gs.cu:183
Return the device pointer for an associated Fortran array.
Definition device.F90:113
Copy data between host and device (or device and device)
Definition device.F90:72
Definition comm.F90:1
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
integer, public pe_rank
MPI rank.
Definition comm.F90:59
Device abstraction, common interface for various accelerators.
Definition device.F90:34
subroutine, public device_event_record(event, stream)
Record a device event.
Definition device.F90:1644
integer, parameter, public host_to_device
Definition device.F90:48
subroutine, public device_free(x_d)
Deallocate memory on the device.
Definition device.F90:243
subroutine, public device_event_destroy(event)
Destroy a device event.
Definition device.F90:1623
subroutine, public device_alloc(x_d, s)
Allocate memory on the device.
Definition device.F90:212
subroutine, public device_stream_create_with_priority(stream, flags, prio)
Create a device stream/command queue with priority.
Definition device.F90:1500
subroutine, public device_stream_wait_event(stream, event, flags)
Synchronize a device stream with an event.
Definition device.F90:1544
subroutine, public device_event_create(event, flags)
Create a device event queue.
Definition device.F90:1589
integer, public strm_high_prio
High priority stream setting.
Definition device.F90:66
subroutine, public device_stream_destroy(stream)
Destroy a device stream/command queue.
Definition device.F90:1522
Defines a gather-scatter communication method.
Definition gs_comm.f90:34
integer, parameter, public gs_vec_nc
Maximum number of components handled by the fused vector (multi-component) halo exchange used by gs_o...
Definition gs_comm.f90:50
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.
Definition htable.f90:52
integer, parameter, public c_rp
Definition num_types.f90:15
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Implements a dynamic stack ADT.
Definition stack.f90:49
Utilities.
Definition utils.f90:35
Gather-scatter communication method.
Definition gs_comm.f90:53
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.
Definition htable.f90:102
Integer based stack.
Definition stack.f90:77
#define max(a, b)
Definition tensor.cu:40