40 use,
intrinsic :: iso_c_binding
41#ifdef HAVE_COARRAY_EVENTS
42 use,
intrinsic :: iso_fortran_env, only : atomic_int_kind, event_type
44 use,
intrinsic :: iso_fortran_env, only : atomic_int_kind
78 real(kind=
rp),
allocatable :: gs_caf_recv_buf(:)[:]
79 integer :: gs_caf_buf_size = 0
84 integer :: gs_caf_mode = 0
91 integer(kind=atomic_int_kind),
allocatable :: gs_caf_data_ready(:)[:]
92 integer(kind=atomic_int_kind),
allocatable :: gs_caf_buf_ready(:)[:]
101 integer,
allocatable :: gs_caf_send_count(:)
102 integer,
allocatable :: gs_caf_recv_count(:)
104#ifdef HAVE_COARRAY_EVENTS
116 type(event_type),
allocatable :: gs_caf_data_ready_ev[:]
117 type(event_type),
allocatable :: gs_caf_buf_ready_ev[:]
118 logical :: gs_caf_event_in_use = .false.
131 real(kind=
rp),
allocatable :: send_buf(:)
133 integer,
allocatable :: send_len(:), recv_len(:)
135 integer,
allocatable :: send_offset(:), recv_offset(:)
137 integer,
allocatable :: dest_offset(:)
139 integer,
allocatable :: send_img(:), recv_img(:)
143 integer,
allocatable :: sync_img(:)
146 logical :: send_started = .false.
150 integer :: parity = 0
166 class(
gs_caf_t),
intent(inout) :: this
170 integer,
allocatable :: dest_xchg(:)[:]
171 logical,
allocatable :: in_neigh(:)
172 integer :: i, nsend, nrecv, send_total, recv_total, max_total, n_neigh
173 integer :: me, env_len
174 character(len=64) :: env_val
177 if (gs_caf_mode .eq. 0)
then
178 call get_environment_variable(
"NEKO_GS_CAF_SIGNALING", env_val, env_len)
179 if (env_len .gt. 0 .and. env_val(1:env_len) .eq.
"atomic")
then
181 allocate(gs_caf_data_ready(0:
pe_size - 1)[*])
182 allocate(gs_caf_buf_ready(0:
pe_size - 1)[*])
183 allocate(gs_caf_send_count(0:
pe_size - 1))
184 allocate(gs_caf_recv_count(0:
pe_size - 1))
185 gs_caf_send_count = 0
186 gs_caf_recv_count = 0
191 call atomic_define(gs_caf_data_ready(i), 0_atomic_int_kind)
192 call atomic_define(gs_caf_buf_ready(i), 0_atomic_int_kind)
194 else if (env_len .gt. 0 .and. env_val(1:env_len) .eq.
"event")
then
195#ifdef HAVE_COARRAY_EVENTS
198 call neko_error(
"NEKO_GS_CAF_SIGNALING=event requires a Fortran " // &
199 "compiler with coarray events support")
206#ifdef HAVE_COARRAY_EVENTS
212 if (.not.
allocated(gs_caf_data_ready_ev))
then
213 allocate(gs_caf_data_ready_ev[*])
214 allocate(gs_caf_buf_ready_ev[*])
219 call this%init_order(send_pe, recv_pe)
221 nsend =
size(this%send_pe)
222 nrecv =
size(this%recv_pe)
224 allocate(this%send_len(nsend), this%send_offset(nsend), &
225 this%send_img(nsend), this%dest_offset(nsend))
226 allocate(this%recv_len(nrecv), this%recv_offset(nrecv), &
227 this%recv_img(nrecv))
232 this%recv_len(i) = this%recv_dof(this%recv_pe(i))%size()
233 this%recv_offset(i) = recv_total
234 recv_total = recv_total + this%recv_len(i)
235 this%recv_img(i) = this%recv_pe(i) + 1
241 this%send_len(i) = this%send_dof(this%send_pe(i))%size()
242 this%send_offset(i) = send_total
243 send_total = send_total + this%send_len(i)
244 this%send_img(i) = this%send_pe(i) + 1
255 max_total = recv_total
256 call co_max(max_total)
257 max_total =
max(1, max_total)
262 if (
gs_vec_nc * max_total .gt. gs_caf_buf_size)
then
263 if (
allocated(gs_caf_recv_buf))
deallocate(gs_caf_recv_buf)
264 allocate(gs_caf_recv_buf(2 *
gs_vec_nc * max_total)[*])
267 this%vec_supported = .true.
275 allocate(dest_xchg(0:
pe_size - 1)[*])
277 dest_xchg(me - 1)[this%recv_img(i)] = this%recv_offset(i)
281 this%dest_offset(i) = dest_xchg(this%send_pe(i))
283 deallocate(dest_xchg)
289 allocate(in_neigh(0:
pe_size - 1))
292 in_neigh(this%send_pe(i)) = .true.
295 in_neigh(this%recv_pe(i)) = .true.
297 n_neigh = count(in_neigh)
298 allocate(this%sync_img(n_neigh))
301 if (in_neigh(i))
then
302 n_neigh = n_neigh + 1
303 this%sync_img(n_neigh) = i + 1
313 call neko_error(
"Coarray Fortran support not built; reconfigure with " // &
314 "a coarray-capable Fortran compiler")
322 class(
gs_caf_t),
intent(inout) :: this
324 if (
allocated(this%send_buf))
deallocate(this%send_buf)
325 if (
allocated(this%send_len))
deallocate(this%send_len)
326 if (
allocated(this%recv_len))
deallocate(this%recv_len)
327 if (
allocated(this%send_offset))
deallocate(this%send_offset)
328 if (
allocated(this%recv_offset))
deallocate(this%recv_offset)
329 if (
allocated(this%dest_offset))
deallocate(this%dest_offset)
330 if (
allocated(this%send_img))
deallocate(this%send_img)
331 if (
allocated(this%recv_img))
deallocate(this%recv_img)
332 if (
allocated(this%sync_img))
deallocate(this%sync_img)
334 call this%free_order()
335 call this%free_dofs()
345 class(
gs_caf_t),
intent(inout) :: this
346 integer,
intent(in) :: n
347 real(kind=
rp),
dimension(n),
intent(inout) :: u
348 integer,
intent(in) :: tag
349 type(c_ptr),
intent(inout) :: deps
350 type(c_ptr),
intent(inout) :: strm
352 integer :: i, j, dst, off, dimg, ndst, doff, half_off
353 integer,
pointer :: sp(:)
354 integer(kind=atomic_int_kind) :: flag
357 half_off = this%parity * gs_caf_buf_size
360 do i = 1,
size(this%send_pe)
361 dst = this%send_pe(i)
362 off = this%send_offset(i)
363 ndst = this%send_len(i)
364 dimg = this%send_img(i)
365 doff = this%dest_offset(i)
366 sp => this%send_dof(dst)%array()
367 do concurrent(j = 1:ndst)
368 this%send_buf(off + j) = u(sp(j))
370 gs_caf_recv_buf(half_off + doff + 1 : half_off + doff + ndst)[dimg] &
371 = this%send_buf(off + 1 : off + ndst)
373#ifdef HAVE_COARRAY_EVENTS
378 if (gs_caf_event_in_use)
then
379 call neko_error(
"Event-mode coarray gather-scatter does not " // &
380 "support overlapping gs ops on different instances")
382 gs_caf_event_in_use = .true.
386 if (this%send_started)
then
387 if (
size(this%send_pe) .gt. 0)
then
388 event wait(gs_caf_buf_ready_ev, until_count=
size(this%send_pe))
391 this%send_started = .true.
394 do i = 1,
size(this%send_pe)
395 dst = this%send_pe(i)
396 off = this%send_offset(i)
397 ndst = this%send_len(i)
398 dimg = this%send_img(i)
399 doff = this%dest_offset(i)
400 sp => this%send_dof(dst)%array()
401 do concurrent(j = 1:ndst)
402 this%send_buf(off + j) = u(sp(j))
404 gs_caf_recv_buf(half_off + doff + 1 : half_off + doff + ndst)[dimg] &
405 = this%send_buf(off + 1 : off + ndst)
413 event post(gs_caf_data_ready_ev[dimg])
417 me_rank = this_image() - 1
422 do i = 1,
size(this%send_pe)
423 dst = this%send_pe(i)
424 off = this%send_offset(i)
425 ndst = this%send_len(i)
426 sp => this%send_dof(dst)%array()
427 do concurrent(j = 1:ndst)
428 this%send_buf(off + j) = u(sp(j))
436 do i = 1,
size(this%send_pe)
437 off = this%send_offset(i)
438 ndst = this%send_len(i)
439 dimg = this%send_img(i)
440 doff = this%dest_offset(i)
443 call atomic_ref(flag, gs_caf_buf_ready(this%send_pe(i)))
444 if (int(flag) .ge. gs_caf_send_count(this%send_pe(i)) - 1)
exit
447 gs_caf_recv_buf(half_off + doff + 1 : half_off + doff + ndst)[dimg] &
448 = this%send_buf(off + 1 : off + ndst)
450 gs_caf_send_count(this%send_pe(i)) = &
451 gs_caf_send_count(this%send_pe(i)) + 1
452 call atomic_define(gs_caf_data_ready(me_rank)[dimg], &
453 int(gs_caf_send_count(this%send_pe(i)), atomic_int_kind))
457 call neko_error(
"Coarray Fortran support not built")
464 class(
gs_caf_t),
intent(inout) :: this
465 integer,
intent(in) :: tag
473 class(
gs_caf_t),
intent(inout) :: this
474 integer,
intent(in) :: n
475 real(kind=
rp),
dimension(n),
intent(inout) :: u
476 type(c_ptr),
intent(inout) :: strm
479 integer :: i, j, src, off, nsrc, half_off
480 integer,
pointer ::
sp(:)
481 integer(kind=atomic_int_kind) :: flag
484 half_off = this%parity * gs_caf_buf_size
487 if (
allocated(this%sync_img))
then
488 if (
size(this%sync_img) .gt. 0)
then
489 sync images(this%sync_img)
492#ifdef HAVE_COARRAY_EVENTS
494 if (
size(this%recv_pe) .gt. 0)
then
495 event wait(gs_caf_data_ready_ev, until_count=
size(this%recv_pe))
501 do i = 1,
size(this%recv_pe)
502 gs_caf_recv_count(this%recv_pe(i)) = &
503 gs_caf_recv_count(this%recv_pe(i)) + 1
505 call atomic_ref(flag, gs_caf_data_ready(this%recv_pe(i)))
506 if (int(flag) .ge. gs_caf_recv_count(this%recv_pe(i)))
exit
511 do i = 1,
size(this%recv_pe)
512 src = this%recv_pe(i)
513 off = this%recv_offset(i)
514 nsrc = this%recv_len(i)
515 sp => this%recv_dof(src)%array()
519 do concurrent(j = 1:nsrc)
520 u(
sp(j)) = u(
sp(j)) + gs_caf_recv_buf(half_off + off + j)
524 do concurrent(j = 1:nsrc)
525 u(
sp(j)) = u(
sp(j)) * gs_caf_recv_buf(half_off + off + j)
529 do concurrent(j = 1:nsrc)
530 u(
sp(j)) = min(u(
sp(j)), gs_caf_recv_buf(half_off + off + j))
534 do concurrent(j = 1:nsrc)
535 u(
sp(j)) =
max(u(
sp(j)), gs_caf_recv_buf(half_off + off + j))
538 call neko_error(
"Unknown operation in gs_nbwait_caf")
545 me_rank = this_image() - 1
546 do i = 1,
size(this%recv_pe)
547 call atomic_define(gs_caf_buf_ready(me_rank)[this%recv_img(i)], &
548 int(gs_caf_recv_count(this%recv_pe(i)), atomic_int_kind))
550#ifdef HAVE_COARRAY_EVENTS
552 do i = 1,
size(this%recv_pe)
553 event post(gs_caf_buf_ready_ev[this%recv_img(i)])
555 gs_caf_event_in_use = .false.
560 this%parity = 1 - this%parity
562 call neko_error(
"Coarray Fortran support not built")
571 class(
gs_caf_t),
intent(inout) :: this
572 integer,
intent(in) :: n, nc
573 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
574 integer,
intent(in) :: tag
575 type(c_ptr),
intent(inout) :: deps
576 type(c_ptr),
intent(inout) :: strm
578 integer :: i, j, c, dst, off, dimg, ndst, doff, half_off
579 integer,
pointer :: sp(:)
580 integer(kind=atomic_int_kind) :: flag
583 half_off = this%parity * gs_caf_buf_size
586 do i = 1,
size(this%send_pe)
587 dst = this%send_pe(i)
588 off = this%send_offset(i)
589 ndst = this%send_len(i)
590 dimg = this%send_img(i)
591 doff = this%dest_offset(i)
592 sp => this%send_dof(dst)%array()
594 do concurrent(j = 1:ndst)
595 this%send_buf(nc*off + (c-1)*ndst + j) = u((c-1)*n + sp(j))
598 gs_caf_recv_buf(half_off + nc*doff + 1 : half_off + nc*doff + nc*ndst) &
599 [dimg] = this%send_buf(nc*off + 1 : nc*off + nc*ndst)
601#ifdef HAVE_COARRAY_EVENTS
603 if (gs_caf_event_in_use)
then
604 call neko_error(
"Event-mode coarray gather-scatter does not " // &
605 "support overlapping gs ops on different instances")
607 gs_caf_event_in_use = .true.
609 if (this%send_started)
then
610 if (
size(this%send_pe) .gt. 0)
then
611 event wait(gs_caf_buf_ready_ev, until_count=
size(this%send_pe))
614 this%send_started = .true.
617 do i = 1,
size(this%send_pe)
618 dst = this%send_pe(i)
619 off = this%send_offset(i)
620 ndst = this%send_len(i)
621 dimg = this%send_img(i)
622 doff = this%dest_offset(i)
623 sp => this%send_dof(dst)%array()
625 do concurrent(j = 1:ndst)
626 this%send_buf(nc*off + (c-1)*ndst + j) = u((c-1)*n + sp(j))
629 gs_caf_recv_buf(half_off + nc*doff + 1 : half_off + nc*doff + nc*ndst) &
630 [dimg] = this%send_buf(nc*off + 1 : nc*off + nc*ndst)
632 event post(gs_caf_data_ready_ev[dimg])
636 me_rank = this_image() - 1
638 do i = 1,
size(this%send_pe)
639 dst = this%send_pe(i)
640 off = this%send_offset(i)
641 ndst = this%send_len(i)
642 sp => this%send_dof(dst)%array()
644 do concurrent(j = 1:ndst)
645 this%send_buf(nc*off + (c-1)*ndst + j) = u((c-1)*n + sp(j))
650 do i = 1,
size(this%send_pe)
651 off = this%send_offset(i)
652 ndst = this%send_len(i)
653 dimg = this%send_img(i)
654 doff = this%dest_offset(i)
657 call atomic_ref(flag, gs_caf_buf_ready(this%send_pe(i)))
658 if (int(flag) .ge. gs_caf_send_count(this%send_pe(i)) - 1)
exit
661 gs_caf_recv_buf(half_off + nc*doff + 1 : half_off + nc*doff + nc*ndst) &
662 [dimg] = this%send_buf(nc*off + 1 : nc*off + nc*ndst)
664 gs_caf_send_count(this%send_pe(i)) = &
665 gs_caf_send_count(this%send_pe(i)) + 1
666 call atomic_define(gs_caf_data_ready(me_rank)[dimg], &
667 int(gs_caf_send_count(this%send_pe(i)), atomic_int_kind))
671 call neko_error(
"Coarray Fortran support not built")
677 class(
gs_caf_t),
intent(inout) :: this
678 integer,
intent(in) :: tag, nc
683 class(
gs_caf_t),
intent(inout) :: this
684 integer,
intent(in) :: n, nc
685 real(kind=
rp),
dimension(nc*n),
intent(inout) :: u
686 type(c_ptr),
intent(inout) :: strm
689 integer :: i, j, c, src, off, nsrc, half_off
690 integer,
pointer ::
sp(:)
691 integer(kind=atomic_int_kind) :: flag
694 half_off = this%parity * gs_caf_buf_size
697 if (
allocated(this%sync_img))
then
698 if (
size(this%sync_img) .gt. 0)
then
699 sync images(this%sync_img)
702#ifdef HAVE_COARRAY_EVENTS
704 if (
size(this%recv_pe) .gt. 0)
then
705 event wait(gs_caf_data_ready_ev, until_count=
size(this%recv_pe))
709 do i = 1,
size(this%recv_pe)
710 gs_caf_recv_count(this%recv_pe(i)) = &
711 gs_caf_recv_count(this%recv_pe(i)) + 1
713 call atomic_ref(flag, gs_caf_data_ready(this%recv_pe(i)))
714 if (int(flag) .ge. gs_caf_recv_count(this%recv_pe(i)))
exit
719 do i = 1,
size(this%recv_pe)
720 src = this%recv_pe(i)
721 off = this%recv_offset(i)
722 nsrc = this%recv_len(i)
723 sp => this%recv_dof(src)%array()
728 do concurrent(j = 1:nsrc)
729 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) + &
730 gs_caf_recv_buf(half_off + nc*off + (c-1)*nsrc + j)
736 do concurrent(j = 1:nsrc)
737 u((c-1)*n +
sp(j)) = u((c-1)*n +
sp(j)) * &
738 gs_caf_recv_buf(half_off + nc*off + (c-1)*nsrc + j)
744 do concurrent(j = 1:nsrc)
745 u((c-1)*n +
sp(j)) = min(u((c-1)*n +
sp(j)), &
746 gs_caf_recv_buf(half_off + nc*off + (c-1)*nsrc + j))
752 do concurrent(j = 1:nsrc)
753 u((c-1)*n +
sp(j)) =
max(u((c-1)*n +
sp(j)), &
754 gs_caf_recv_buf(half_off + nc*off + (c-1)*nsrc + j))
758 call neko_error(
"Unknown operation in gs_nbwait_vec_caf")
763 me_rank = this_image() - 1
764 do i = 1,
size(this%recv_pe)
765 call atomic_define(gs_caf_buf_ready(me_rank)[this%recv_img(i)], &
766 int(gs_caf_recv_count(this%recv_pe(i)), atomic_int_kind))
768#ifdef HAVE_COARRAY_EVENTS
770 do i = 1,
size(this%recv_pe)
771 event post(gs_caf_buf_ready_ev[this%recv_img(i)])
773 gs_caf_event_in_use = .false.
777 this%parity = 1 - this%parity
779 call neko_error(
"Coarray Fortran support not built")
integer, public pe_size
MPI size of communicator.
Defines Coarray Fortran gather-scatter communication.
subroutine gs_nbrecv_caf(this, tag)
No-op for coarrays: senders push into the receiver's buffer, so the receive side does not need to pos...
subroutine gs_nbrecv_vec_caf(this, tag, nc)
No-op: senders push into the receiver's buffer.
subroutine gs_nbsend_caf(this, u, n, tag, deps, strm)
Pack u into per-peer slabs and put each slab into the remote image's recv_buf. Double buffering means...
subroutine gs_caf_init(this, send_pe, recv_pe)
Initialise Coarray Fortran based communication method.
subroutine gs_nbwait_caf(this, u, n, op, strm)
Wait for all incoming puts and reduce them into u. In sync mode a sync_images bracket pairs with the ...
integer, parameter, public gs_caf_signal_event
subroutine gs_nbsend_vec_caf(this, u, n, nc, tag, deps, strm)
Fused nc-component put. Each peer slab is nc consecutive component blocks; the remote placement offse...
integer, parameter, public gs_caf_signal_atomic
subroutine gs_caf_free(this)
Deallocate Coarray Fortran based communication method. The shared module-level recv coarray is intent...
integer, parameter, public gs_caf_signal_sync
subroutine gs_nbwait_vec_caf(this, u, n, nc, op, strm)
Fused nc-component wait/reduce for the coarray backend.
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
integer, parameter, public sp
integer, parameter, public rp
Global precision used in computations.
Implements a dynamic stack ADT.
Gather-scatter communication using Coarray Fortran (F2008). Each image puts directly into the (module...
Gather-scatter communication method.