9.2
general documentation
cs_base_hip.h
Go to the documentation of this file.
1#ifndef CS_BASE_HIP_H
2#define CS_BASE_HIP_H
3
4/*============================================================================
5 * Definitions, global variables, and base functions for HIP
6 *============================================================================*/
7
8/*
9 This file is part of code_saturne, a general-purpose CFD tool.
10
11 Copyright (C) 1998-2026 EDF S.A.
12
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 2 of the License, or (at your option) any later
16 version.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21 details.
22
23 You should have received a copy of the GNU General Public License along with
24 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
25 Street, Fifth Floor, Boston, MA 02110-1301, USA.
26*/
27
28/*----------------------------------------------------------------------------*/
29
30#include "base/cs_defs.h"
31
32#if defined(HAVE_HIP)
33
34#if defined(__HIPCC__)
35#include "hip/hip_runtime.h"
36#endif
37
38/*----------------------------------------------------------------------------
39 * Standard C library headers
40 *----------------------------------------------------------------------------*/
41
42#if defined(HAVE_NCCL)
43#include <nccl.h>
44#endif
45
46/*----------------------------------------------------------------------------
47 * Local headers
48 *----------------------------------------------------------------------------*/
49
50#include "base/cs_base_accel.h"
51#include "base/cs_log.h"
52
53/*=============================================================================
54 * Macro definitions
55 *============================================================================*/
56
57#define CS_HIP_CHECK(a) { \
58 hipError_t _l_ret_code = a; \
59 if (hipSuccess != _l_ret_code) { \
60 bft_error(__FILE__, __LINE__, 0, "[HIP error] %d: %s\n running: %s", \
61 _l_ret_code, ::hipGetErrorString(_l_ret_code), #a); \
62 } \
63 }
64
65#define CS_HIP_CHECK_CALL(a, file_name, line_num) { \
66 hipError_t _l_ret_code = a; \
67 if (hipSuccess != _l_ret_code) { \
68 bft_error(file_name, line_num, 0, "[HIP error] %d: %s\n running: %s", \
69 _l_ret_code, ::hipGetErrorString(_l_ret_code), #a); \
70 } \
71 }
72
73/* For all current compute capabilities, the warp size is 32; If it ever
74 changes, it can be obtained through hipDeviceProp_t, so we could then
75 replace this macro with a global variable */
76#if defined(__GFX8__) || defined(__GFX9__)
77 #define CS_HIP_WARP_SIZE 64
78using cs_hip_mask_t = uint64_t;
79#else
80 #define CS_HIP_WARP_SIZE 32
81using cs_hip_mask_t = uint32_t;
82#endif
83
84/*============================================================================
85 * Type definitions
86 *============================================================================*/
87
88/*=============================================================================
89 * Global variable definitions
90 *============================================================================*/
91
92extern int cs_glob_hip_device_id;
93
94/* Other device parameters */
95
96extern int cs_glob_hip_shared_mem_per_block;
97extern int cs_glob_hip_max_threads_per_block;
98extern int cs_glob_hip_max_block_size;
99extern int cs_glob_hip_max_blocks;
100extern int cs_glob_hip_n_mp; /* Number of multiprocessors */
101
102#if defined(HAVE_NCCL)
103
104extern ncclComm_t cs_glob_nccl_comm;
105
106/* NCCL Datatypes associated with code_saturne datatypes */
107extern ncclDataType_t cs_datatype_to_nccl[];
108
109#endif
110
111/* Allow graphs for kernel launches ? May interfere with profiling (nsys),
112 so can be deactivated. */
113
114extern bool cs_glob_hip_allow_graph;
115
116/*============================================================================
117 * Semi-private function prototypes
118 *
119 * The following functions are intended to be used by the common
120 * host-device memory management functions from cs_base_accel.c, and
121 * not directly by the user.
122 *============================================================================*/
123
124/*----------------------------------------------------------------------------*/
125/*
126 * \brief Copy data from host to device.
127 *
128 * This is simply a wrapper over hipMemcpy.
129 *
130 * A safety check is added.
131 *
132 * \param [out] dst pointer to destination data
133 * \param [in] src pointer to source data
134 * \param [in] size size of data to copy
135 */
136/*----------------------------------------------------------------------------*/
137
138void
139cs_hip_copy_h2d(void *dst,
140 const void *src,
141 size_t size);
142
143/*----------------------------------------------------------------------------*/
144/*
145 * \brief Copy data from host to device, possibly returning on the host
146 * before the copy is finished.
147 *
148 * This is simply a wrapper over hipMemcpyAsync.
149 *
150 * A safety check is added.
151 *
152 * \param [out] dst pointer to destination data
153 * \param [in] src pointer to source data
154 * \param [in] size size of data to copy
155 *
156 * \returns pointer to allocated memory.
157 */
158/*----------------------------------------------------------------------------*/
159
160void
161cs_hip_copy_h2d_async(void *dst,
162 const void *src,
163 size_t size);
164
165/*----------------------------------------------------------------------------*/
166/*
167 * \brief Copy data from device to host.
168 *
169 * This is simply a wrapper over hipMemcpy.
170 *
171 * A safety check is added.
172 *
173 * \param [out] dst pointer to destination data
174 * \param [in] src pointer to source data
175 * \param [in] size size of data to copy
176 *
177 * \returns pointer to allocated memory.
178 */
179/*----------------------------------------------------------------------------*/
180
181void
182cs_hip_copy_d2h(void *dst,
183 const void *src,
184 size_t size);
185
186/*----------------------------------------------------------------------------*/
187/*
188 * \brief Copy data from host to device.
189 *
190 * This is simply a wrapper over hipMemcpy.
191 *
192 * A safety check is added.
193 *
194 * \param [out] dst pointer to destination data
195 * \param [in] src pointer to source data
196 * \param [in] size size of data to copy
197 *
198 * \returns pointer to allocated memory.
199 */
200/*----------------------------------------------------------------------------*/
201
202void
203cs_hip_copy_d2h_async(void *dst,
204 const void *src,
205 size_t size);
206
207/*----------------------------------------------------------------------------*/
208/*
209 * \brief Copy data from device to device.
210 *
211 * This is simply a wrapper over hipMemcpy.
212 *
213 * A safety check is added.
214 *
215 * \param [out] dst pointer to destination data
216 * \param [in] src pointer to source data
217 * \param [in] size size of data to copy
218 */
219/*----------------------------------------------------------------------------*/
220
221void
222cs_hip_copy_d2d(void *dst,
223 const void *src,
224 size_t size);
225
226/*----------------------------------------------------------------------------*/
227/*
228 * \brief Get host pointer for a managed or device pointer.
229 *
230 * This function can be called with a pointer inside an allocated block of
231 * memory, so is not restricted to values returned by CS_MALLOC_HD.
232 *
233 * This makes it possible to check whether a pointer to an array inside
234 * a larger array is shared or accessible from the device only
235 * (for example when grouping allocations).
236 *
237 * \param [in] ptr pointer to device data
238 *
239 * \return pointer to host data if shared or mapped at the HIP level,
240 * NULL otherwise.
241 */
242/*----------------------------------------------------------------------------*/
243
244void *
245cs_hip_get_host_ptr(const void *ptr);
246
247/*=============================================================================
248 * Inline function prototypes
249 *============================================================================*/
250
251/*----------------------------------------------------------------------------*/
264/*----------------------------------------------------------------------------*/
265
266inline unsigned int
267cs_hip_grid_size(cs_lnum_t n,
268 unsigned int block_size)
269{
270 return (n % block_size) ? n/block_size + 1 : n/block_size;
271}
272
273#if defined(__HIPCC__)
274
275/*----------------------------------------------------------------------------
276 * Synchronize of copy a cs_real_t type array from the host to a device.
277 *
278 * parameters:
279 * val_h <-- pointer to host data
280 * n_vals <-- number of data values
281 * device_id <-- associated device id
282 * stream <-- associated stream (for async prefetch only)
283 * val_d --> matching pointer on device
284 * buf_d --> matching allocation pointer on device (should be freed
285 * after use if non-null)
286 *----------------------------------------------------------------------------*/
287
288template <typename T>
289void
290cs_sync_or_copy_h2d(const T *val_h,
291 cs_lnum_t n_vals,
292 int device_id,
293 hipStream_t stream,
294 const T **val_d,
295 void **buf_d)
296{
297 const T *_val_d = NULL;
298 void *_buf_d = NULL;
299
300 if (val_h != NULL) {
301
302 cs_alloc_mode_t alloc_mode = cs_check_device_ptr(val_h);
303 size_t size = n_vals * sizeof(T);
304
305 if (alloc_mode == CS_ALLOC_HOST) {
306 CS_HIP_CHECK(hipMalloc(&_buf_d, size));
307 cs_hip_copy_h2d(_buf_d, val_h, size);
308 _val_d = (const T *)_buf_d;
309 }
310 else {
311 _val_d = (const T *)cs_get_device_ptr_const((const void *)val_h);
312
313 if (alloc_mode < CS_ALLOC_HOST_DEVICE_SHARED)
314 cs_sync_h2d(val_h);
315 }
316
317 }
318
319 *val_d = _val_d;
320 *buf_d = _buf_d;
321}
322
323/*=============================================================================
324 * Public function prototypes
325 *============================================================================*/
326
327/*----------------------------------------------------------------------------*/
328/*
329 * \brief Return stream handle from stream pool.
330 *
331 * If the requested stream id is higher than the current number of streams,
332 * one or more new streams will be created, so that size of the stream pool
333 * matches at least stream_id+1.
334 *
335 * By default, the first stream (with id 0) will be used for most operations,
336 * while stream id 1 will be used for operations which can be done
337 * concurrently, such as memory prefetching.
338 *
339 * Additional streams can be used for independent tasks, though opportunities
340 * for this are limited in the current code (this would probably also require
341 * associating different MPI communicators with each task).
342 *
343 * \param [in] stream_id id or requested stream
344 *
345 * \returns handle to requested stream
346 */
347/*----------------------------------------------------------------------------*/
348
349hipStream_t
350cs_hip_get_stream(int stream_id);
351
352/*----------------------------------------------------------------------------*/
353/*
354 * \brief Return stream handle used for prefetching.
355 *
356 * By default, a single stream is created specifically for prefetching.
357 *
358 * \returns handle to prefetching stream
359 */
360/*----------------------------------------------------------------------------*/
361
362hipStream_t
363cs_hip_get_stream_prefetch(void);
364
365/*----------------------------------------------------------------------------*/
375/*----------------------------------------------------------------------------*/
376
377int
378cs_hip_get_stream_id(hipStream_t stream);
379
380/*----------------------------------------------------------------------------*/
395/*----------------------------------------------------------------------------*/
396
397void
398cs_hip_get_2_stage_reduce_buffers(int stream_id,
399 cs_lnum_t n_elts,
400 size_t elt_size,
401 unsigned int grid_size,
402 void* &r_grid,
403 void* &r_reduce,
404 void* &r_host);
405
406#endif /* defined(__NVCC__) */
407
408/*----------------------------------------------------------------------------*/
409/*
410 * \brief Log information on available HIP devices.
411 *
412 * \param[in] log_id id of log file in which to print information
413 */
414/*----------------------------------------------------------------------------*/
415
416void
418
419/*----------------------------------------------------------------------------*/
420/*
421 * \brief Log information on available HIP version.
422 *
423 * \param[in] log_id id of log file in which to print information
424 */
425/*----------------------------------------------------------------------------*/
426
427void
429
430/*----------------------------------------------------------------------------*/
431/*
432 * \brief Log information on HIP compiler.
433 *
434 * \param[in] log_id id of log file in which to print information
435 */
436/*----------------------------------------------------------------------------*/
437
438void
440
441/*----------------------------------------------------------------------------*/
447/*----------------------------------------------------------------------------*/
448
449extern "C" void
451
452/*----------------------------------------------------------------------------*/
453/*
454 * \brief Set HIP device based on MPI rank and number of devices.
455 *
456 * \param[in] comm associated MPI communicator
457 * \param[in] ranks_per_node number of ranks per node (min and max)
458 *
459 * \return selected device id, or -1 if no usable device is available
460 */
461/*----------------------------------------------------------------------------*/
462
463int
465
466/*----------------------------------------------------------------------------*/
467/*
468 * \brief Return currently selected HIP devices.
469 *
470 * \return selected device id, or -1 if no usable device is available
471 */
472/*----------------------------------------------------------------------------*/
473
474int
476
477#endif /* CS_HAVE_HIP */
478
479/*----------------------------------------------------------------------------*/
480
481#endif /* CS_BASE_HIP_H */
void cs_base_hip_nccl_info(cs_log_t log_id)
Log information on NCCL.
Definition: cs_base_hip.cpp:698
void cs_base_hip_device_info(cs_log_t log_id)
Log information on available HIP devices.
Definition: cs_base_hip.cpp:604
int cs_base_hip_get_device(void)
Return currently selected HIP devices.
Definition: cs_base_hip.cpp:816
void cs_base_hip_compiler_info(cs_log_t log_id)
Log information on HIP compiler.
Definition: cs_base_hip.cpp:683
int cs_base_hip_select_default_device(void)
Set HIP device based on MPI rank and number of devices.
Definition: cs_base_hip.cpp:727
void cs_base_hip_version_info(cs_log_t log_id)
Log information on available HIP version.
Definition: cs_base_hip.cpp:662
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:325
cs_log_t
Definition: cs_log.h:44
void cs_sync_h2d(const void *ptr)
Synchronize data from host to device.
Definition: cs_mem.h:935
cs_alloc_mode_t cs_check_device_ptr(const void *ptr)
Check if a pointer is associated with a device.
Definition: cs_mem.h:727
const void * cs_get_device_ptr_const(const void *ptr)
Return matching device pointer for a given constant pointer.
Definition: cs_mem.h:687
cs_alloc_mode_t
Definition: cs_mem.h:46
@ CS_ALLOC_HOST
Definition: cs_mem.h:48
@ CS_ALLOC_HOST_DEVICE_SHARED
Definition: cs_mem.h:53