All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
detail/error.hpp
1 /*
2  * Copyright (c) 2020-2025, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <rmm/error.hpp>
20 
21 #include <cuda_runtime_api.h>
22 
23 #include <cassert>
24 #include <exception>
25 #include <iostream>
26 #include <string>
27 #include <type_traits>
28 
29 #define STRINGIFY_DETAIL(x) #x
30 #define RMM_STRINGIFY(x) STRINGIFY_DETAIL(x)
31 
56 #define RMM_EXPECTS(...) \
57  GET_RMM_EXPECTS_MACRO(__VA_ARGS__, RMM_EXPECTS_3, RMM_EXPECTS_2) \
58  (__VA_ARGS__)
59 #define GET_RMM_EXPECTS_MACRO(_1, _2, _3, NAME, ...) NAME
60 #define RMM_EXPECTS_3(_condition, _reason, _exception_type) \
61  do { \
62  static_assert(std::is_base_of_v<std::exception, _exception_type>); \
63  /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
64  (!!(_condition)) ? static_cast<void>(0) \
65  : throw _exception_type{std::string{"RMM failure at: "} + __FILE__ + ":" + \
66  RMM_STRINGIFY(__LINE__) + ": " + _reason}; \
67  } while (0)
68 #define RMM_EXPECTS_2(_condition, _reason) RMM_EXPECTS_3(_condition, _reason, rmm::logic_error)
69 
82 #define RMM_FAIL(...) \
83  GET_RMM_FAIL_MACRO(__VA_ARGS__, RMM_FAIL_2, RMM_FAIL_1) \
84  (__VA_ARGS__)
85 #define GET_RMM_FAIL_MACRO(_1, _2, NAME, ...) NAME
86 #define RMM_FAIL_2(_what, _exception_type) \
87  /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
88  throw _exception_type \
89  { \
90  std::string{"RMM failure at:"} + __FILE__ + ":" + RMM_STRINGIFY(__LINE__) + ": " + _what \
91  }
92 #define RMM_FAIL_1(_what) RMM_FAIL_2(_what, rmm::logic_error)
93 
115 #define RMM_CUDA_TRY(...) \
116  GET_RMM_CUDA_TRY_MACRO(__VA_ARGS__, RMM_CUDA_TRY_2, RMM_CUDA_TRY_1) \
117  (__VA_ARGS__)
118 #define GET_RMM_CUDA_TRY_MACRO(_1, _2, NAME, ...) NAME
119 #define RMM_CUDA_TRY_2(_call, _exception_type) \
120  do { \
121  cudaError_t const error = (_call); \
122  if (cudaSuccess != error) { \
123  cudaGetLastError(); \
124  /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
125  throw _exception_type{std::string{"CUDA error at: "} + __FILE__ + ":" + \
126  RMM_STRINGIFY(__LINE__) + ": " + cudaGetErrorName(error) + " " + \
127  cudaGetErrorString(error)}; \
128  } \
129  } while (0)
130 #define RMM_CUDA_TRY_1(_call) RMM_CUDA_TRY_2(_call, rmm::cuda_error)
131 
146 #define RMM_CUDA_TRY_ALLOC(...) \
147  GET_RMM_CUDA_TRY_ALLOC_MACRO(__VA_ARGS__, RMM_CUDA_TRY_ALLOC_2, RMM_CUDA_TRY_ALLOC_1) \
148  (__VA_ARGS__)
149 #define GET_RMM_CUDA_TRY_ALLOC_MACRO(_1, _2, NAME, ...) NAME
150 
151 #define RMM_CUDA_TRY_ALLOC_2(_call, num_bytes) \
152  do { \
153  cudaError_t const error = (_call); \
154  if (cudaSuccess != error) { \
155  cudaGetLastError(); \
156  auto const msg = std::string{"CUDA error (failed to allocate "} + \
157  std::to_string(num_bytes) + " bytes) at: " + __FILE__ + ":" + \
158  RMM_STRINGIFY(__LINE__) + ": " + cudaGetErrorName(error) + " " + \
159  cudaGetErrorString(error); \
160  if (cudaErrorMemoryAllocation == error) { throw rmm::out_of_memory{msg}; } \
161  throw rmm::bad_alloc{msg}; \
162  } \
163  } while (0)
164 
165 #define RMM_CUDA_TRY_ALLOC_1(_call) \
166  do { \
167  cudaError_t const error = (_call); \
168  if (cudaSuccess != error) { \
169  cudaGetLastError(); \
170  auto const msg = std::string{"CUDA error at: "} + __FILE__ + ":" + RMM_STRINGIFY(__LINE__) + \
171  ": " + cudaGetErrorName(error) + " " + cudaGetErrorString(error); \
172  if (cudaErrorMemoryAllocation == error) { throw rmm::out_of_memory{msg}; } \
173  throw rmm::bad_alloc{msg}; \
174  } \
175  } while (0)
176 
202 #ifdef NDEBUG
203 #define RMM_ASSERT_CUDA_SUCCESS(_call) \
204  do { \
205  (_call); \
206  } while (0);
207 #else
208 #define RMM_ASSERT_CUDA_SUCCESS(_call) \
209  do { \
210  cudaError_t const status__ = (_call); \
211  if (status__ != cudaSuccess) { \
212  std::cerr << "CUDA Error detected. " << cudaGetErrorName(status__) << " " \
213  << cudaGetErrorString(status__) << std::endl; \
214  } \
215  /* NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay) */ \
216  assert(status__ == cudaSuccess); \
217  } while (0)
218 #endif