Eigen  5.0.1
 
Loading...
Searching...
No Matches
GpuRuntime.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// This Source Code Form is subject to the terms of the Mozilla
5// Public License v. 2.0. If a copy of the MPL was not distributed
6// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
7// SPDX-FileCopyrightText: The Eigen Authors
8// SPDX-License-Identifier: MPL-2.0
9
10// Host-side helpers shared by the CUDA and HIP paths of the Tensor GPU device: reporting of failed runtime calls
11// and checked kernel launches. Written against the gpu* aliases of GpuHipCudaDefines.inc, so it is only meaningful
12// inside that alias window (TensorDeviceGpu.h includes it there) and neither includes nor undefines the .inc files
13// itself; outside the window it is inert, so a standalone parse sees nothing. The macros below may expand after the
14// window closes, which is why each of them only calls a function defined here.
15#if defined(EIGEN_CORE_GPU_HIP_CUDA_DEFINES_H) && !defined(EIGEN_CORE_UTIL_GPU_RUNTIME_H)
16#define EIGEN_CORE_UTIL_GPU_RUNTIME_H
17
18#include <cstdio>
19#include <cstdlib>
20#include <utility>
21
22namespace Eigen {
23namespace internal {
24
25// Prints `file:line: call: error name: description` to stderr and stops: std::abort() where assertions are
26// compiled out, a failed eigen_assert otherwise, so a debugger or the test harness sees the usual assertion.
27inline void gpu_runtime_check_failed(gpuError_t error, const char* expression, const char* file, int line) {
28 std::fprintf(stderr, "%s:%d: %s: %s: %s\n", file, line, expression, gpuGetErrorName(error), gpuGetErrorString(error));
29#if defined(EIGEN_NO_DEBUG)
30 std::abort();
31#else
32 eigen_assert(false && "GPU runtime call failed");
33#endif
34}
35
36inline void gpu_runtime_check(gpuError_t error, const char* expression, const char* file, int line) {
37 if (error != gpuSuccess) gpu_runtime_check_failed(error, expression, file, line);
38}
39
40} // namespace internal
41} // namespace Eigen
42
43// EIGEN_GPU_RUNTIME_CHECK(call) evaluates a runtime-API call once and reports a failure through
44// gpu_runtime_check_failed(). Define the macro before including the module to route failures elsewhere. There is
45// no mode that ignores the result: a failed call has not done its work, and a sticky error leaves the context
46// unusable for every later call.
47#if !defined(EIGEN_GPU_RUNTIME_CHECK)
48#define EIGEN_GPU_RUNTIME_CHECK(expr) \
49 do { \
50 ::Eigen::internal::gpu_runtime_check((expr), #expr, __FILE__, __LINE__); \
51 } while (0)
52#endif
53
54#if defined(EIGEN_GPUCC)
55namespace Eigen {
56namespace internal {
57
58// Enqueues `kernel` on `stream` and reports a launch failure through EIGEN_GPU_RUNTIME_CHECK. hip-clang accepts the
59// <<<>>> syntax, so CUDA and HIP share one definition; the kernel is passed as the function pointer the occupancy
60// API takes as well. With EIGEN_GPU_SYNC_LAUNCHES defined every launch is followed by a checked synchronization of
61// its stream, so an execution failure is reported at the launch that caused it rather than at a later call.
62template <typename... KernelArgs, typename... Args>
63void gpu_launch(void (*kernel)(KernelArgs...), dim3 grid, dim3 block, size_t shared_mem, gpuStream_t stream,
64 Args&&... args) {
65 // clang-format off
66 kernel<<<grid, block, shared_mem, stream>>>(std::forward<Args>(args)...);
67 // clang-format on
68 EIGEN_GPU_RUNTIME_CHECK(gpuGetLastError());
69#if defined(EIGEN_GPU_SYNC_LAUNCHES)
70 EIGEN_GPU_RUNTIME_CHECK(gpuStreamSynchronize(stream));
71#endif
72}
73
74} // namespace internal
75} // namespace Eigen
76#endif // EIGEN_GPUCC
77
78#endif // EIGEN_CORE_UTIL_GPU_RUNTIME_H