error.hpp
1 /*
2  * Copyright (c) 2020, 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/logger.hpp>
20 
21 #include <cuda_runtime_api.h>
22 
23 #include <cassert>
24 #include <iostream>
25 #include <stdexcept>
26 #include <string>
27 
28 namespace rmm {
36 struct logic_error : public std::logic_error {
37  using std::logic_error::logic_error;
38 };
39 
44 struct cuda_error : public std::runtime_error {
45  using std::runtime_error::runtime_error;
46 };
47 
52 class bad_alloc : public std::bad_alloc {
53  public:
54  bad_alloc(const char* w) : std::bad_alloc{}, _what{std::string{std::bad_alloc::what()} + ": " + w}
55  {
56  }
57 
58  bad_alloc(std::string const& w) : bad_alloc(w.c_str()) {}
59 
60  virtual ~bad_alloc() = default;
61 
62  virtual const char* what() const noexcept { return _what.c_str(); }
63 
64  private:
65  std::string _what;
66 };
67 
72 class out_of_range : public std::out_of_range {
73  using std::out_of_range::out_of_range;
74 };
75 
76 } // namespace rmm
77 
78 #define STRINGIFY_DETAIL(x) #x
79 #define RMM_STRINGIFY(x) STRINGIFY_DETAIL(x)
80 
104 #define RMM_EXPECTS(...) \
105  GET_RMM_EXPECTS_MACRO(__VA_ARGS__, RMM_EXPECTS_3, RMM_EXPECTS_2) \
106  (__VA_ARGS__)
107 #define GET_RMM_EXPECTS_MACRO(_1, _2, _3, NAME, ...) NAME
108 #define RMM_EXPECTS_3(_condition, _exception_type, _reason) \
109  (!!(_condition)) ? static_cast<void>(0) : throw _exception_type \
110  { \
111  "RMM failure at: " __FILE__ ":" RMM_STRINGIFY(__LINE__) ": " _reason \
112  }
113 #define RMM_EXPECTS_2(_condition, _reason) RMM_EXPECTS_3(_condition, rmm::logic_error, _reason)
114 
127 #define RMM_FAIL(...) \
128  GET_RMM_FAIL_MACRO(__VA_ARGS__, RMM_FAIL_2, RMM_FAIL_1) \
129  (__VA_ARGS__)
130 #define GET_RMM_FAIL_MACRO(_1, _2, NAME, ...) NAME
131 #define RMM_FAIL_2(_what, _exception_type) \
132  throw _exception_type{"RMM failure at:" __FILE__ ":" RMM_STRINGIFY(__LINE__) ": " _what};
133 #define RMM_FAIL_1(_what) RMM_FAIL_2(_what, rmm::logic_error)
134 
156 #define RMM_CUDA_TRY(...) \
157  GET_RMM_CUDA_TRY_MACRO(__VA_ARGS__, RMM_CUDA_TRY_2, RMM_CUDA_TRY_1) \
158  (__VA_ARGS__)
159 #define GET_RMM_CUDA_TRY_MACRO(_1, _2, NAME, ...) NAME
160 #define RMM_CUDA_TRY_2(_call, _exception_type) \
161  do { \
162  cudaError_t const error = (_call); \
163  if (cudaSuccess != error) { \
164  cudaGetLastError(); \
165  throw _exception_type{std::string{"CUDA error at: "} + __FILE__ + ":" + \
166  RMM_STRINGIFY(__LINE__) + ": " + cudaGetErrorName(error) + " " + \
167  cudaGetErrorString(error)}; \
168  } \
169  } while (0)
170 #define RMM_CUDA_TRY_1(_call) RMM_CUDA_TRY_2(_call, rmm::cuda_error)
171 
197 #ifdef NDEBUG
198 #define RMM_ASSERT_CUDA_SUCCESS(_call) \
199  do { \
200  (_call); \
201  } while (0);
202 #else
203 #define RMM_ASSERT_CUDA_SUCCESS(_call) \
204  do { \
205  cudaError_t const status__ = (_call); \
206  if (status__ != cudaSuccess) { \
207  std::cerr << "CUDA Error detected. " << cudaGetErrorName(status__) << " " \
208  << cudaGetErrorString(status__) << std::endl; \
209  } \
210  assert(status__ == cudaSuccess); \
211  } while (0)
212 #endif
213 
217 #ifdef NDEBUG
218 #define RMM_LOGGING_ASSERT(_expr) (void)0
219 #elif SPDLOG_ACTIVE_LEVEL < SPDLOG_LEVEL_OFF
220 #define RMM_LOGGING_ASSERT(_expr) \
221  do { \
222  bool const success = (_expr); \
223  if (!success) { \
224  RMM_LOG_CRITICAL( \
225  "[" __FILE__ ":" RMM_STRINGIFY(__LINE__) "] Assertion " RMM_STRINGIFY(_expr) " failed."); \
226  rmm::logger().flush(); \
227  assert(success); \
228  } \
229  } while (0)
230 #else
231 #define RMM_LOGGING_ASSERT(_expr) assert((_expr));
232 #endif
rmm::bad_alloc
Exception thrown when an RMM allocation fails.
Definition: error.hpp:52
rmm::logic_error
Exception thrown when logical precondition is violated.
Definition: error.hpp:36
rmm::cuda_error
Exception thrown when a CUDA error is encountered.
Definition: error.hpp:44
rmm::out_of_range
Exception thrown when attempting to access outside of a defined range.
Definition: error.hpp:72