EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_GPURuntime.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Robert Marskar <robert.marskar@sintef.no>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
23#ifndef EBGEOMETRY_GPURUNTIME_HPP
24#define EBGEOMETRY_GPURUNTIME_HPP
25
26// Our includes
27#include "EBGeometry_GPU.hpp"
28
29#if defined(EBGEOMETRY_CUDA) || defined(EBGEOMETRY_HIP) || defined(EBGEOMETRY_DOXYGEN)
30
31// Std includes (EBGEOMETRY_GPU_CHECK needs fprintf/abort; the wrappers need size_t).
32#include <cstddef>
33#include <cstdio>
34#include <cstdlib>
35
36// Backend runtime header. HIP is checked FIRST: hipcc on the NVIDIA platform defines both
37// __HIPCC__ and __CUDACC__, and there the hip* entry points exist and forward to cuda*, so
38// mapping to hip* whenever __HIPCC__ is defined is correct on both HIP platforms.
39#if defined(EBGEOMETRY_HIP)
40#include <hip/hip_runtime.h> // NOT pre-included by the compiler driver; must be explicit.
41#elif defined(EBGEOMETRY_CUDA)
42#include <cuda_runtime.h> // nvcc pre-includes this; spelled out for hygiene.
43#endif
44
45namespace EBGeometry {
46
54namespace GPU {
55
56#if defined(EBGEOMETRY_DOXYGEN)
57
61using Error = int;
62
66using MemcpyKind = int;
67
71inline constexpr Error Success = 0;
72
76inline constexpr MemcpyKind MemcpyHostToDevice = 1;
77
81inline constexpr MemcpyKind MemcpyDeviceToHost = 2;
82
89[[nodiscard]] inline Error
90memAlloc(void** a_devicePtr, size_t a_numBytes) noexcept;
91
97[[nodiscard]] inline Error
98memFree(void* a_devicePtr) noexcept;
99
107[[nodiscard]] inline Error
108memAllocManaged(void** a_ptr, size_t a_numBytes) noexcept;
109
116[[nodiscard]] inline Error
117memAllocHost(void** a_ptr, size_t a_numBytes) noexcept;
118
128[[nodiscard]] inline Error
129memAllocHostMapped(void** a_ptr, size_t a_numBytes) noexcept;
130
137[[nodiscard]] inline Error
138memFreeHost(void* a_ptr) noexcept;
139
148[[nodiscard]] inline Error
149memcpy(void* a_dst, const void* a_src, size_t a_numBytes, MemcpyKind a_kind) noexcept;
150
156[[nodiscard]] inline Error
157getDeviceCount(int* a_count) noexcept;
158
163[[nodiscard]] inline Error
164getLastError() noexcept;
165
171[[nodiscard]] inline Error
173
180[[nodiscard]] inline const char*
181getErrorString(Error a_error) noexcept;
182
190[[nodiscard]] inline bool
191isShutdownError(Error a_error) noexcept;
192
201[[nodiscard]] inline const char*
202getErrorHint(Error a_error) noexcept;
203
204#elif defined(EBGEOMETRY_HIP)
205
206using Error = hipError_t;
207using MemcpyKind = hipMemcpyKind;
208
209inline constexpr Error Success = hipSuccess;
210inline constexpr MemcpyKind MemcpyHostToDevice = hipMemcpyHostToDevice;
211inline constexpr MemcpyKind MemcpyDeviceToHost = hipMemcpyDeviceToHost;
212
213[[nodiscard]] inline Error
214memAlloc(void** a_devicePtr, size_t a_numBytes) noexcept
215{
216 return hipMalloc(a_devicePtr, a_numBytes);
217}
218
219[[nodiscard]] inline Error
220memFree(void* a_devicePtr) noexcept
221{
222 return hipFree(a_devicePtr);
223}
224
225[[nodiscard]] inline Error
226memAllocManaged(void** a_ptr, size_t a_numBytes) noexcept
227{
228 return hipMallocManaged(a_ptr, a_numBytes);
229}
230
231[[nodiscard]] inline Error
232memAllocHost(void** a_ptr, size_t a_numBytes) noexcept
233{
234 return hipHostMalloc(a_ptr, a_numBytes, 0u);
235}
236
237[[nodiscard]] inline Error
238memAllocHostMapped(void** a_ptr, size_t a_numBytes) noexcept
239{
240 return hipHostMalloc(a_ptr, a_numBytes, hipHostMallocMapped);
241}
242
243[[nodiscard]] inline Error
244memFreeHost(void* a_ptr) noexcept
245{
246 return hipHostFree(a_ptr);
247}
248
249[[nodiscard]] inline Error
250memcpy(void* a_dst, const void* a_src, size_t a_numBytes, MemcpyKind a_kind) noexcept
251{
252 return hipMemcpy(a_dst, a_src, a_numBytes, a_kind);
253}
254
255[[nodiscard]] inline Error
256getDeviceCount(int* a_count) noexcept
257{
258 return hipGetDeviceCount(a_count);
259}
260
261[[nodiscard]] inline Error
262getLastError() noexcept
263{
264 return hipGetLastError();
265}
266
267[[nodiscard]] inline Error
268deviceSynchronize() noexcept
269{
270 return hipDeviceSynchronize();
271}
272
273[[nodiscard]] inline const char*
274getErrorString(Error a_error) noexcept
275{
276 return hipGetErrorString(a_error);
277}
278
279[[nodiscard]] inline bool
280isShutdownError(Error a_error) noexcept
281{
282 return a_error == hipErrorDeinitialized || a_error == hipErrorContextIsDestroyed;
283}
284
285[[nodiscard]] inline const char*
286getErrorHint(Error a_error) noexcept
287{
288 return (a_error == hipErrorNoBinaryForGpu)
289 ? "\n hint: the binary has no code for this GPU; build for its architecture (--offload-arch, "
290 "HIP_ARCH or CMAKE_HIP_ARCHITECTURES)"
291 : "";
292}
293
294#elif defined(EBGEOMETRY_CUDA)
295
296using Error = cudaError_t;
297using MemcpyKind = cudaMemcpyKind;
298
299inline constexpr Error Success = cudaSuccess;
300inline constexpr MemcpyKind MemcpyHostToDevice = cudaMemcpyHostToDevice;
301inline constexpr MemcpyKind MemcpyDeviceToHost = cudaMemcpyDeviceToHost;
302
303[[nodiscard]] inline Error
304memAlloc(void** a_devicePtr, size_t a_numBytes) noexcept
305{
306 return cudaMalloc(a_devicePtr, a_numBytes);
307}
308
309[[nodiscard]] inline Error
310memFree(void* a_devicePtr) noexcept
311{
312 return cudaFree(a_devicePtr);
313}
314
315[[nodiscard]] inline Error
316memAllocManaged(void** a_ptr, size_t a_numBytes) noexcept
317{
318 return cudaMallocManaged(a_ptr, a_numBytes, cudaMemAttachGlobal);
319}
320
321[[nodiscard]] inline Error
322memAllocHost(void** a_ptr, size_t a_numBytes) noexcept
323{
324 return cudaHostAlloc(a_ptr, a_numBytes, cudaHostAllocDefault);
325}
326
327[[nodiscard]] inline Error
328memAllocHostMapped(void** a_ptr, size_t a_numBytes) noexcept
329{
330 return cudaHostAlloc(a_ptr, a_numBytes, cudaHostAllocMapped);
331}
332
333[[nodiscard]] inline Error
334memFreeHost(void* a_ptr) noexcept
335{
336 return cudaFreeHost(a_ptr);
337}
338
339[[nodiscard]] inline Error
340memcpy(void* a_dst, const void* a_src, size_t a_numBytes, MemcpyKind a_kind) noexcept
341{
342 return cudaMemcpy(a_dst, a_src, a_numBytes, a_kind);
343}
344
345[[nodiscard]] inline Error
346getDeviceCount(int* a_count) noexcept
347{
348 return cudaGetDeviceCount(a_count);
349}
350
351[[nodiscard]] inline Error
352getLastError() noexcept
353{
354 return cudaGetLastError();
355}
356
357[[nodiscard]] inline Error
358deviceSynchronize() noexcept
359{
360 return cudaDeviceSynchronize();
361}
362
363[[nodiscard]] inline const char*
364getErrorString(Error a_error) noexcept
365{
366 return cudaGetErrorString(a_error);
367}
368
369[[nodiscard]] inline bool
370isShutdownError(Error a_error) noexcept
371{
372 return a_error == cudaErrorCudartUnloading || a_error == cudaErrorContextIsDestroyed;
373}
374
375[[nodiscard]] inline const char*
376getErrorHint(Error a_error) noexcept
377{
378 return (a_error == cudaErrorUnsupportedPtxVersion || a_error == cudaErrorNoKernelImageForDevice)
379 ? "\n hint: the binary has no machine code for this GPU, and the driver cannot compile its PTX; "
380 "build for the GPU's architecture (-arch, CUDA_ARCH or CMAKE_CUDA_ARCHITECTURES), or update "
381 "the driver"
382 : "";
383}
384
385#endif
386
387} // namespace GPU
388} // namespace EBGeometry
389
398#define EBGEOMETRY_GPU_CHECK(x) \
399 do { \
400 const EBGeometry::GPU::Error ebgeometry_gpu_err = (x); \
401 if (ebgeometry_gpu_err != EBGeometry::GPU::Success) { \
402 std::fprintf(stderr, \
403 "EBGeometry GPU error: %s\n call: %s\n file: %s\n line: %d%s\n", \
404 EBGeometry::GPU::getErrorString(ebgeometry_gpu_err), \
405 #x, \
406 __FILE__, \
407 __LINE__, \
408 EBGeometry::GPU::getErrorHint(ebgeometry_gpu_err)); \
409 std::abort(); \
410 } \
411 } while (0)
412
413#endif // EBGEOMETRY_CUDA || EBGEOMETRY_HIP || EBGEOMETRY_DOXYGEN
414
415#endif // EBGEOMETRY_GPURUNTIME_HPP
GPU portability layer: host/device decoration macros and backend detection.
Error memAllocHostMapped(void **a_ptr, size_t a_numBytes) noexcept
Allocate page-locked (pinned) host memory that is additionally mapped into the device address space f...
Error memFree(void *a_devicePtr) noexcept
Free device memory allocated with memAlloc (cudaFree / hipFree).
Error memcpy(void *a_dst, const void *a_src, size_t a_numBytes, MemcpyKind a_kind) noexcept
Copy memory between host and device (cudaMemcpy / hipMemcpy). Synchronous.
Error getDeviceCount(int *a_count) noexcept
Get the number of available GPU devices (cudaGetDeviceCount / hipGetDeviceCount).
Error deviceSynchronize() noexcept
Block until the device has finished all preceding work (cudaDeviceSynchronize / hipDeviceSynchronize)...
int Error
Backend runtime error code (cudaError_t under CUDA, hipError_t under HIP).
Definition EBGeometry_GPURuntime.hpp:61
const char * getErrorHint(Error a_error) noexcept
What to do about an error that means the binary has no code this GPU can run: the binary was built fo...
Error memAlloc(void **a_devicePtr, size_t a_numBytes) noexcept
Allocate device memory (cudaMalloc / hipMalloc).
const char * getErrorString(Error a_error) noexcept
Get the human-readable description of an error code (cudaGetErrorString / hipGetErrorString).
Error memAllocManaged(void **a_ptr, size_t a_numBytes) noexcept
Allocate managed (unified) memory accessible from host and device (cudaMallocManaged / hipMallocManag...
Error memFreeHost(void *a_ptr) noexcept
Free page-locked host memory allocated with memAllocHost (cudaFreeHost / hipHostFree).
Error getLastError() noexcept
Get and clear the last runtime error (cudaGetLastError / hipGetLastError).
constexpr MemcpyKind MemcpyDeviceToHost
Device-to-host copy direction (cudaMemcpyDeviceToHost / hipMemcpyDeviceToHost).
Definition EBGeometry_GPURuntime.hpp:81
bool isShutdownError(Error a_error) noexcept
True for the errors a runtime call returns once the runtime has shut down at program exit (cudaErrorC...
constexpr Error Success
Success value of Error (cudaSuccess / hipSuccess).
Definition EBGeometry_GPURuntime.hpp:71
Error memAllocHost(void **a_ptr, size_t a_numBytes) noexcept
Allocate page-locked (pinned) host memory (cudaHostAlloc / hipHostMalloc).
int MemcpyKind
Memory-copy direction (cudaMemcpyKind under CUDA, hipMemcpyKind under HIP).
Definition EBGeometry_GPURuntime.hpp:66
constexpr MemcpyKind MemcpyHostToDevice
Host-to-device copy direction (cudaMemcpyHostToDevice / hipMemcpyHostToDevice).
Definition EBGeometry_GPURuntime.hpp:76
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26