9.2
general documentation
cs_array_hip.h
Go to the documentation of this file.
1#include "hip/hip_runtime.h"
2/*============================================================================
3 * Array handling utilities.
4 *============================================================================*/
5
6/*
7 This file is part of code_saturne, a general-purpose CFD tool.
8
9 Copyright (C) 1998-2026 EDF S.A.
10
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free Software
13 Foundation; either version 2 of the License, or (at your option) any later
14 version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
23 Street, Fifth Floor, Boston, MA 02110-1301, USA.
24*/
25
26/*----------------------------------------------------------------------------*/
27
28/*----------------------------------------------------------------------------
29 * Standard C and C++ library headers
30 *----------------------------------------------------------------------------*/
31
32#include <string.h>
33
34/*----------------------------------------------------------------------------
35 * Local headers
36 *----------------------------------------------------------------------------*/
37
38#include "base/cs_defs.h"
39#include "base/cs_base_hip.h"
40
41/*----------------------------------------------------------------------------*/
42
43/*=============================================================================
44 * Macro definitions
45 *============================================================================*/
46
47/*============================================================================
48 * Type definitions
49 *============================================================================*/
50
51/*============================================================================
52 * Global variables
53 *============================================================================*/
54
55/*=============================================================================
56 * Public inline function prototypes
57 *============================================================================*/
58
59/*=============================================================================
60 * Public function prototypes
61 *============================================================================*/
62
63/* Default kernel that loops over an integer range and calls a device functor.
64 This kernel uses a grid_size-stride loop and thus guarantees that all
65 integers are processed, even if the grid is smaller.
66 All arguments *must* be passed by value to avoid passing CPU references
67 to the GPU. */
68
69template <typename T, size_t stride>
70__global__ void
72 const T ref_val,
73 const int size_arrs,
74 T **array_ptrs)
75{
76 // grid_size-stride loop
77 for (cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x; id < n;
78 id += blockDim.x * gridDim.x) {
79 for (int j = 0; j < size_arrs; j++) {
80 for (size_t k = 0; k < stride; k++) {
81 array_ptrs[j][id*stride + k] = ref_val;
82 } // end loop stride
83 }
84 } // end loop arrays
85}
86
87template <typename T, size_t stride>
88__global__ void
90 const T *ref_val,
91 const int size_arrs,
92 T **array_ptrs)
93{
94 // grid_size-stride loop
95 for (cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x; id < n;
96 id += blockDim.x * gridDim.x) {
97 for (int j = 0; j < size_arrs; j++) {
98 for (size_t k = 0; k < stride; k++) {
99 array_ptrs[j][id*stride + k] = ref_val[k];
100 } // end loop stride
101 }
102 } // end loop arrays
103}
104
105template <typename T, size_t stride>
106__global__ void
108 const T ref_val,
109 T *array)
110{
111 // grid_size-stride loop
112 for (cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x; id < n;
113 id += blockDim.x * gridDim.x) {
114 for (size_t k = 0; k < stride; k++) {
115 array[id*stride + k] = ref_val;
116 } // end loop stride
117 } // end loop arrays
118}
119
120template <typename T, size_t stride>
121__global__ void
123 const T *ref_val,
124 T *array)
125{
126 // grid_size-stride loop
127 for (cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x; id < n;
128 id += blockDim.x * gridDim.x) {
129 for (size_t k = 0; k < stride; k++) {
130 array[id*stride + k] = *ref_val;
131 } // end loop stride
132 } // end loop arrays
133}
134
135template <typename T, size_t stride>
136__global__ void
138 T *array)
139{
140 T c = static_cast<T>(0);
141
142 // grid_size-stride loop
143 for (cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x; id < n;
144 id += blockDim.x * gridDim.x) {
145 for (size_t k = 0; k < stride; k++) {
146 array[id*stride + k] = c;
147 } // end loop stride
148 } // end loop arrays
149}
150
151/*----------------------------------------------------------------------------*/
167/*----------------------------------------------------------------------------*/
168
169template <typename T, size_t stride, typename... Arrays>
170void
171cs_arrays_set_value(hipStream_t stream,
172 bool async,
173 cs_lnum_t n_elts,
174 T *ref_val,
175 Arrays&&... arrays)
176{
177 const long block_size_ = 256;
178 const long grid_size_ = (n_elts % block_size_) ?
179 n_elts/block_size_ + 1 : n_elts/block_size_;
180
181 /* Explicit expansion of arrays */
182 const int size_arrs = sizeof...(arrays);
183 T* _array_ptrs[] = {arrays ...};
184
185 if (size_arrs > 1) {
186 hipGraph_t graph;
187 hipGraphExec_t graph_exec = NULL;
188
189 CS_HIP_CHECK(hipStreamBeginCapture(stream, hipStreamCaptureModeGlobal));
190 for (int j = 0; j < size_arrs; j++) {
191 hip_kernel_set_value<T, stride><<<grid_size_, block_size_, 0, stream>>>
192 (n_elts, ref_val, _array_ptrs[j]);
193 }
194 CS_HIP_CHECK(hipStreamEndCapture(stream, &graph));
195
196 CS_HIP_CHECK(hipGraphInstantiate(&graph_exec, graph,
197 nullptr, nullptr, 0));
198 CS_HIP_CHECK(hipGraphLaunch(graph_exec, stream));
199
200 /* For multiple arrays, sync even if async is required,
201 to ensure the graph is not destroyed before all kernels
202 are scheduled */
203
204 CS_HIP_CHECK(hipStreamSynchronize(stream));
205 CS_HIP_CHECK(hipGetLastError());
206
207 CS_HIP_CHECK(hipGraphDestroy(graph));
208 CS_HIP_CHECK(hipGraphExecDestroy(graph_exec));
209 }
210
211 else {
212 hip_kernel_set_value<T, stride><<<grid_size_, block_size_, 0, stream>>>
213 (n_elts, ref_val, _array_ptrs[0]);
214
215 if (async == false) {
216 CS_HIP_CHECK(hipStreamSynchronize(stream));
217 CS_HIP_CHECK(hipGetLastError());
218 }
219 }
220}
221
222/*----------------------------------------------------------------------------*/
238/*----------------------------------------------------------------------------*/
239
240template <typename T, size_t stride, typename... Arrays>
241void
242cs_arrays_set_value(hipStream_t stream,
243 bool async,
244 cs_lnum_t n_elts,
245 T ref_val,
246 Arrays&&... arrays)
247{
248 const long block_size_ = 256;
249 const long grid_size_ = (n_elts % block_size_) ?
250 n_elts/block_size_ + 1 : n_elts/block_size_;
251
252 /* Explicit expansion of arrays */
253 const int size_arrs = sizeof...(arrays);
254 T* _array_ptrs[] = {arrays ...};
255
256 if (size_arrs > 1) {
257 hipGraph_t graph;
258 hipGraphExec_t graph_exec = NULL;
259
260 CS_HIP_CHECK(hipStreamBeginCapture(stream, hipStreamCaptureModeGlobal));
261
262 for (int j = 0; j < size_arrs; j++) {
263 hip_kernel_set_value<T, stride><<<grid_size_, block_size_, 0, stream>>>
264 (n_elts, ref_val, _array_ptrs[j]);
265 }
266 CS_HIP_CHECK(hipStreamEndCapture(stream, &graph));
267
268 CS_HIP_CHECK(hipGraphInstantiate(&graph_exec, graph,
269 nullptr, nullptr, 0));
270 CS_HIP_CHECK(hipGraphLaunch(graph_exec, stream));
271
272 /* For multiple arrays, sync even if async is required,
273 to ensure the graph is not destroyed before all kernels
274 are scheduled */
275
276 CS_HIP_CHECK(hipStreamSynchronize(stream));
277 CS_HIP_CHECK(hipGetLastError());
278
279 CS_HIP_CHECK(hipGraphDestroy(graph));
280 CS_HIP_CHECK(hipGraphExecDestroy(graph_exec));
281 }
282
283 else {
284 hip_kernel_set_value<T, stride><<<grid_size_, block_size_, 0, stream>>>
285 (n_elts, ref_val, _array_ptrs[0]);
286
287 if (async == false) {
288 CS_HIP_CHECK(hipStreamSynchronize(stream));
289 CS_HIP_CHECK(hipGetLastError());
290 }
291 }
292}
293
294/*----------------------------------------------------------------------------*/
310/*----------------------------------------------------------------------------*/
311
312template <typename T, size_t stride, typename... Arrays>
313void
314cs_arrays_set_zero(hipStream_t stream,
315 bool async,
316 cs_lnum_t n_elts,
317 Arrays&&... arrays)
318{
319 const long block_size_ = 256;
320 const long grid_size_ = (n_elts % block_size_) ?
321 n_elts/block_size_ + 1 : n_elts/block_size_;
322
323 /* Explicit expansion of arrays */
324 const int size_arrs = sizeof...(arrays);
325 T* _array_ptrs[] = {arrays ...};
326
327 if (size_arrs > 1) {
328 hipGraph_t graph;
329 hipGraphExec_t graph_exec = NULL;
330
331 CS_HIP_CHECK(hipStreamBeginCapture(stream, hipStreamCaptureModeGlobal));
332 for (int j = 0; j < size_arrs; j++) {
333 cs_hip_kernel_set_zero<T, stride><<<grid_size_, block_size_, 0, stream>>>
334 (n_elts, _array_ptrs[j]);
335 }
336 CS_HIP_CHECK(hipStreamEndCapture(stream, &graph));
337
338 CS_HIP_CHECK(hipGraphInstantiate(&graph_exec, graph,
339 nullptr, nullptr, 0));
340 CS_HIP_CHECK(hipGraphLaunch(graph_exec, stream));
341
342 /* For multiple arrays, sync even if async is required,
343 to ensure the graph is not destroyed before all kernels
344 are scheduled */
345
346 CS_HIP_CHECK(hipStreamSynchronize(stream));
347 CS_HIP_CHECK(hipGetLastError());
348
349 CS_HIP_CHECK(hipGraphDestroy(graph));
350 CS_HIP_CHECK(hipGraphExecDestroy(graph_exec));
351 }
352
353 else {
354 cs_hip_kernel_set_zero<T, stride><<<grid_size_, block_size_, 0, stream>>>
355 (n_elts, _array_ptrs[0]);
356
357 if (async == false) {
358 CS_HIP_CHECK(hipStreamSynchronize(stream));
359 CS_HIP_CHECK(hipGetLastError());
360 }
361 }
362}
363
364/*----------------------------------------------------------------------------*/
377/*----------------------------------------------------------------------------*/
378
379template <typename T>
380void
381cs_array_copy(hipStream_t stream,
382 bool async,
383 const cs_lnum_t size,
384 const T* src,
385 T* dest)
386{
387 CS_HIP_CHECK(hipMemcpyAsync(dest, src, size*sizeof(T),
388 hipMemcpyDeviceToDevice, stream));
389 if (async == false) {
390 CS_HIP_CHECK(hipStreamSynchronize(stream));
391 CS_HIP_CHECK(hipGetLastError());
392 }
393}
394
395/*----------------------------------------------------------------------------*/
void cs_arrays_set_zero(hipStream_t stream, bool async, cs_lnum_t n_elts, Arrays &&... arrays)
Assign values to all elements of multiple arrays. ref_val is input as a pointer or an array.
Definition: cs_array_hip.h:314
__global__ void cs_hip_kernel_set_zero(cs_lnum_t n, T *array)
Definition: cs_array_hip.h:137
void cs_array_copy(hipStream_t stream, bool async, const cs_lnum_t size, const T *src, T *dest)
Copy values from an array to another of the same dimensions.
Definition: cs_array_hip.h:381
__global__ void hip_kernel_set_value(cs_lnum_t n, const T ref_val, const int size_arrs, T **array_ptrs)
Definition: cs_array_hip.h:71
void cs_arrays_set_value(hipStream_t stream, bool async, cs_lnum_t n_elts, T *ref_val, Arrays &&... arrays)
Assign values to all elements of multiple arrays. ref_val is input as a pointer or an array.
Definition: cs_array_hip.h:171
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:325
@ k
Definition: cs_field_pointer.h:68