42 use,
intrinsic :: iso_c_binding, only : c_ptr, c_int, c_null_ptr, &
43 c_associated, c_sizeof, c_size_t
49 type(c_ptr) :: local_gs_d = c_null_ptr
50 type(c_ptr) :: local_dof_gs_d = c_null_ptr
51 type(c_ptr) :: local_gs_dof_d = c_null_ptr
52 type(c_ptr) :: shared_gs_d = c_null_ptr
53 type(c_ptr) :: shared_dof_gs_d = c_null_ptr
54 type(c_ptr) :: shared_gs_dof_d = c_null_ptr
55 type(c_ptr) :: local_blk_len_d = c_null_ptr
56 type(c_ptr) :: shared_blk_len_d = c_null_ptr
57 type(c_ptr) :: local_blk_off_d = c_null_ptr
58 type(c_ptr) :: shared_blk_off_d = c_null_ptr
70 subroutine hip_gather_kernel(v, m, o, dg, u, n, gd, nb, b, bo, op, strm) &
71 bind(c, name =
'hip_gather_kernel')
72 use,
intrinsic :: iso_c_binding
74 integer(c_int) :: m, n, nb, o, op
75 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
81 bind(c, name =
'hip_scatter_kernel')
82 use,
intrinsic :: iso_c_binding
84 integer(c_int) :: m, n, nb
85 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
91 subroutine cuda_gather_kernel(v, m, o, dg, u, n, gd, nb, b, bo, op, strm) &
92 bind(c, name =
'cuda_gather_kernel')
93 use,
intrinsic :: iso_c_binding
95 integer(c_int) :: m, n, nb, o, op
96 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
102 bind(c, name =
'cuda_scatter_kernel')
103 use,
intrinsic :: iso_c_binding
105 integer(c_int) :: m, n, nb
106 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
111 subroutine opencl_gather_kernel(v, m, o, dg, u, n, gd, nb, b, bo, op, &
112 strm) bind(c, name = 'opencl_gather_kernel')
113 use,
intrinsic :: iso_c_binding
115 integer(c_int) :: m, n, nb, o, op
116 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
122 bind(c, name =
'opencl_scatter_kernel')
123 use,
intrinsic :: iso_c_binding
125 integer(c_int) :: m, n, nb
126 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
131 subroutine metal_gather_kernel(v, m, o, dg, u, n, gd, nb, b, bo, op, &
132 strm) bind(c, name = 'metal_gather_kernel')
133 use,
intrinsic :: iso_c_binding
135 integer(c_int) :: m, n, nb, o, op
136 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
137 end subroutine metal_gather_kernel
141 subroutine metal_scatter_kernel(v, m, dg, u, n, gd, nb, b, bo, strm) &
142 bind(c, name =
'metal_scatter_kernel')
143 use,
intrinsic :: iso_c_binding
145 integer(c_int) :: m, n, nb
146 type(c_ptr),
value :: v, u, dg, gd, b, bo, strm
147 end subroutine metal_scatter_kernel
156 integer,
intent(in) :: nlocal
157 integer,
intent(in) :: nshared
158 integer,
intent(in) :: nlcl_blks
159 integer,
intent(in) :: nshrd_blks
164 this%nshared = nshared
166 this%local_gs_d = c_null_ptr
167 this%local_dof_gs_d = c_null_ptr
168 this%local_gs_dof_d = c_null_ptr
169 this%local_blk_len_d = c_null_ptr
170 this%local_blk_off_d = c_null_ptr
171 this%shared_gs_d = c_null_ptr
172 this%shared_dof_gs_d = c_null_ptr
173 this%shared_gs_dof_d = c_null_ptr
174 this%shared_blk_len_d = c_null_ptr
175 this%shared_blk_off_d = c_null_ptr
177 this%shared_on_host = .true.
179#if defined(HAVE_HIP) || defined(HAVE_CUDA) || defined(HAVE_METAL)
192 if (c_associated(this%local_gs_d))
then
196 if (c_associated(this%local_dof_gs_d))
then
200 if (c_associated(this%local_gs_dof_d))
then
204 if (c_associated(this%shared_gs_d))
then
208 if (c_associated(this%shared_dof_gs_d))
then
212 if (c_associated(this%shared_gs_dof_d))
then
216 if (c_associated(this%local_blk_len_d))
then
220 if (c_associated(this%shared_blk_len_d))
then
224 if (c_associated(this%local_blk_off_d))
then
228 if (c_associated(this%shared_blk_off_d))
then
235#if defined(HAVE_HIP) || defined(HAVE_CUDA) || defined(HAVE_METAL)
236 if (c_associated(this%gather_event))
then
240 if (c_associated(this%scatter_event))
then
245 if (c_associated(this%gs_stream))
then
246 this%gs_stream = c_null_ptr
252 subroutine gs_gather_device(this, v, m, o, dg, u, n, gd, nb, b, bo, op, shrd)
253 integer,
intent(in) :: m
254 integer,
intent(in) :: n
255 integer,
intent(in) :: nb
257 real(kind=
rp),
dimension(m),
intent(inout) :: v
258 integer,
dimension(m),
intent(inout) :: dg
259 real(kind=
rp),
dimension(n),
intent(inout) :: u
260 integer,
dimension(m),
intent(inout) :: gd
261 integer,
dimension(nb),
intent(inout) :: b
262 integer,
dimension(nb),
intent(inout) :: bo
263 integer,
intent(in) :: o
264 integer,
intent(in) :: op
265 logical,
intent(in) :: shrd
272 associate(v_d => this%local_gs_d, dg_d => this%local_dof_gs_d, &
273 gd_d => this%local_gs_dof_d, b_d => this%local_blk_len_d, &
274 bo_d => this%local_blk_off_d, strm => this%gs_stream)
276 if (.not. c_associated(v_d))
then
279 real(c_rp) :: rp_dummy
280 integer(c_size_t) :: s
281 s = c_sizeof(rp_dummy) * m
286 if (.not. c_associated(dg_d))
then
289 sync = .false., strm = strm)
292 if (.not. c_associated(gd_d))
then
295 sync = .false., strm = strm)
299 if (.not. c_associated(b_d))
then
302 sync = .false., strm = strm)
305 if (.not. c_associated(bo_d))
then
308 sync = .false., strm = strm)
314 nb, b_d, bo_d, op, strm)
317 nb, b_d, bo_d, op, strm)
320 nb, b_d, bo_d, op, strm)
322 call metal_gather_kernel(v_d, m, o, dg_d, u_d, n, gd_d, &
323 nb, b_d, bo_d, op, strm)
325 call neko_error(
'No device backend configured')
330 associate(v_d => this%shared_gs_d, dg_d => this%shared_dof_gs_d, &
331 gd_d => this%shared_gs_dof_d, b_d => this%shared_blk_len_d, &
332 bo_d => this%shared_blk_off_d, strm => this%gs_stream)
334 if (.not. c_associated(v_d))
then
337 real(c_rp) :: rp_dummy
338 integer(c_size_t) :: s
339 s = c_sizeof(rp_dummy) * m
344 if (.not. c_associated(dg_d))
then
347 sync = .false., strm = strm)
350 if (.not. c_associated(gd_d))
then
353 sync = .false., strm = strm)
357 if (.not. c_associated(b_d))
then
360 sync = .false., strm = strm)
363 if (.not. c_associated(bo_d))
then
366 sync = .false., strm = strm)
373 nb, b_d, bo_d, op, strm)
376 nb, b_d, bo_d, op, strm)
379 nb, b_d, bo_d, op, strm)
381 call metal_gather_kernel(v_d, m, o, dg_d, u_d, n, gd_d, &
382 nb, b_d, bo_d, op, strm)
384 call neko_error(
'No device backend configured')
387#if defined(HAVE_HIP) || defined(HAVE_CUDA) || \
388 defined(have_opencl) || defined(have_metal)
392 if (this%shared_on_host)
then
393 if (this%nshared .eq. m)
then
395 sync = .true., strm = strm)
405 subroutine gs_scatter_device(this, v, m, dg, u, n, gd, nb, b, bo, shrd, event)
406 integer,
intent(in) :: m
407 integer,
intent(in) :: n
408 integer,
intent(in) :: nb
410 real(kind=rp),
dimension(m),
intent(inout) :: v
411 integer,
dimension(m),
intent(inout) :: dg
412 real(kind=rp),
dimension(n),
intent(inout) :: u
413 integer,
dimension(m),
intent(inout) :: gd
414 integer,
dimension(nb),
intent(inout) :: b
415 integer,
dimension(nb),
intent(inout) :: bo
416 logical,
intent(in) :: shrd
420 u_d = device_get_ptr(u)
423 associate(v_d => this%local_gs_d, dg_d => this%local_dof_gs_d, &
424 gd_d => this%local_gs_dof_d, b_d => this%local_blk_len_d, &
425 bo_d => this%local_blk_off_d, strm => this%gs_stream)
436 call metal_scatter_kernel(v_d, m, dg_d, u_d, n, gd_d, nb, b_d, &
439 call neko_error(
'No device backend configured')
443 associate(v_d => this%shared_gs_d, dg_d => this%shared_dof_gs_d, &
444 gd_d => this%shared_gs_dof_d, b_d => this%shared_blk_len_d, &
445 bo_d => this%shared_blk_off_d, strm => this%gs_stream)
447 if (this%shared_on_host)
then
448 call device_memcpy(v, v_d, m, host_to_device, &
449 sync = .false., strm = strm)
462 call metal_scatter_kernel(v_d, m, dg_d, u_d, n, gd_d, nb, b_d, &
465 call neko_error(
'No device backend configured')
470#if defined(HAVE_HIP) || defined(HAVE_CUDA) || \
471 defined(have_opencl) || defined(have_metal)
472 if (c_associated(event))
then
473 call device_event_record(event, this%gs_stream)
475 call device_sync(this%gs_stream)
void opencl_gather_kernel(void *v, int *m, int *o, void *dg, void *u, int *n, void *gd, int *nb, void *b, void *bo, int *op, void *cmd_queue)
void opencl_scatter_kernel(void *v, int *m, void *dg, void *u, int *n, void *gd, int *nb, void *b, void *bo, void *cmd_queue)
void cuda_gather_kernel(void *v, int *m, int *o, void *dg, void *u, int *n, void *gd, int *nb, void *b, void *bo, int *op, cudaStream_t stream)
void cuda_scatter_kernel(void *v, int *m, void *dg, void *u, int *n, void *gd, int *nb, void *b, void *bo, cudaStream_t stream)
Return the device pointer for an associated Fortran array.
Map a Fortran array to a device (allocate and associate)
Copy data between host and device (or device and device)
Synchronize a device or stream.
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.
integer, parameter, public device_to_host
subroutine, public device_event_destroy(event)
Destroy a device event.
type(c_ptr), bind(C), public glb_cmd_queue
Global command queue.
subroutine, public device_event_create(event, flags)
Create a device event queue.
subroutine, public device_memset(x_d, v, s, sync, strm)
Set memory on the device to a value.
Defines a gather-scatter backend.
Generic Gather-scatter backend for accelerators.
subroutine gs_device_init(this, nlocal, nshared, nlcl_blks, nshrd_blks)
Accelerator backend initialisation.
subroutine gs_gather_device(this, v, m, o, dg, u, n, gd, nb, b, bo, op, shrd)
Gather kernel.
subroutine gs_device_free(this)
Dummy backend deallocation.
subroutine gs_scatter_device(this, v, m, dg, u, n, gd, nb, b, bo, shrd, event)
Scatter kernel.
integer, parameter, public c_rp
integer, parameter, public rp
Global precision used in computations.
Gather-scatter backend for offloading devices.