cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
error.hpp
Go to the documentation of this file.
1 
8 #pragma once
9 #ifndef CUDA_API_WRAPPERS_RTC_ERROR_HPP_
10 #define CUDA_API_WRAPPERS_RTC_ERROR_HPP_
11 
12 #include "types.hpp"
13 
14 #include <cuda_runtime_api.h>
15 
16 #include <type_traits>
17 #include <string>
18 #include <stdexcept>
19 
20 namespace cuda {
21 
22 namespace rtc {
23 
24 namespace detail_ {
25 
26 // We would _like_ to define the named status codes here. Unfortunately - we cannot, due to a
27 // C++11 corner-case behavior issues in GCC and/or clang. See:
28 // https://stackoverflow.com/q/73479613/1593077
29 // https://cplusplus.github.io/CWG/issues/1485
30 //
31 // template <> enum types<cuda_cpp>::named_status ...
32 // template <> enum types<ptx>::named_status ...
33 
34 } // namespace detail_
35 
36 namespace status {
37 
41 template <source_kind_t Kind>
42 using named_t = typename rtc::detail_::types<Kind>::named_status;
43 
45 template <source_kind_t Kind>
46 constexpr bool operator==(const status_t<Kind>& lhs, const named_t<Kind>& rhs) { return lhs == static_cast<status_t<Kind> >(rhs); }
47 template <source_kind_t Kind>
48 constexpr bool operator!=(const status_t<Kind>& lhs, const named_t<Kind>& rhs) { return lhs != static_cast<status_t<Kind> >(rhs); }
49 template <source_kind_t Kind>
50 constexpr bool operator==(const named_t<Kind>& lhs, const status_t<Kind>& rhs) { return static_cast<status_t<Kind> >(lhs) == rhs; }
51 template <source_kind_t Kind>
52 constexpr bool operator!=(const named_t<Kind>& lhs, const status_t<Kind>& rhs) { return static_cast<status_t<Kind> >(lhs) != rhs; }
54 
55 } // namespace status
56 
57 } // namespace rtc
58 
59 
63  template <source_kind_t Kind>
65 constexpr bool is_success(rtc::status_t<Kind> status)
66 {
67  return (status == static_cast<rtc::status_t<Kind>>(rtc::status::named_t<Kind>::success));
68 }
70 
74 template <source_kind_t Kind>
75 constexpr bool is_failure(rtc::status_t<Kind> status)
76 {
77  return not is_success<Kind>(status);
78 }
79 
84 inline ::std::string describe(rtc::status_t<cuda_cpp> status)
86 {
87  return nvrtcGetErrorString(status);
88 }
89 
90 #if CUDA_VERSION >= 11010
91 inline ::std::string describe(rtc::status_t<ptx> status)
92 {
93  using named = rtc::status::named_t<ptx>;
94  switch((status_t) status) {
95  case (status_t) named::success: break;
96  case (status_t) named::invalid_program_handle: return "Invalid PTX compilation handle";
97  case (status_t) named::out_of_memory: return "out of memory";
98  case (status_t) named::invalid_input: return "Invalid input for PTX compilation";
99  case (status_t) named::compilation_invocation_incomplete: return "PTX compilation invocation incomplete";
100  case (status_t) named::compilation_failure: return "PTX compilation failure";
101  case (status_t) named::unsupported_ptx_version: return "Unsupported PTX version";
102  case (status_t) named::internal_error: return "Unknown PTX compilation error";
103 #if CUDA_VERSION >= 12010
104  case (status_t) named::unsupported_device_side_sync: return "Unsupported device-side synchronization";
105 #endif
106  default: break;
107  }
108  return "unknown error";
109 }
110 #endif // CUDA_VERSION >= 11010
111 
113 namespace rtc {
114 
122 template <source_kind_t Kind>
123 class runtime_error : public ::std::runtime_error {
124 public:
125  // TODO: Constructor chaining; and perhaps allow for more construction mechanisms?
126  runtime_error(status_t<Kind> error_code) :
127  ::std::runtime_error(describe(error_code)),
128  code_(error_code)
129  { }
130  // I wonder if I should do this the other way around
131  runtime_error(status_t<Kind> error_code, ::std::string what_arg) :
132  ::std::runtime_error(::std::move(what_arg) + ": " + describe(error_code)),
133  code_(error_code)
134  { }
136  runtime_error(static_cast<status_t<Kind>>(error_code)) { }
137  runtime_error(status::named_t<Kind> error_code, const ::std::string& what_arg) :
138  runtime_error(static_cast<status_t<Kind>>(error_code), what_arg) { }
139 
140 protected:
141  runtime_error(status_t<Kind> error_code, ::std::runtime_error err) :
142  ::std::runtime_error(::std::move(err)), code_(error_code)
143  { }
144 
145 public:
146  static runtime_error with_message_override(status_t<Kind> error_code, ::std::string complete_what_arg)
147  {
148  return runtime_error<Kind>(error_code, ::std::runtime_error(complete_what_arg));
149  }
150 
154  status_t<Kind> code() const { return code_; }
155 
156 private:
157  status_t<Kind> code_;
158 };
159 
160 
161 } // namespace rtc
162 
163 // TODO: The following could use ::std::optional arguments - which would
164 // prevent the need for dual versions of the functions - but we're
165 // not writing C++17 here
166 
174 template <source_kind_t Kind>
175 inline void throw_if_error(rtc::status_t<Kind> status, const ::std::string& message) noexcept(false)
176 {
177  if (is_failure<Kind>(status)) { throw rtc::runtime_error<Kind>(status, message); }
178 }
179 
186 template <source_kind_t Kind>
187 inline void throw_if_error(rtc::status_t<Kind> status) noexcept(false)
188 {
189  if (is_failure(status)) { throw rtc::runtime_error<Kind>(status); }
190 }
191 
201 #define throw_if_rtc_error_lazy(Kind, status__, ... ) \
202 do { \
203  ::cuda::rtc::status_t<Kind> tie_status__ = static_cast<::cuda::rtc::status_t<Kind>>(status__); \
204  if (::cuda::is_failure<Kind>(tie_status__)) { \
205  throw ::cuda::rtc::runtime_error<Kind>(tie_status__, (__VA_ARGS__)); \
206  } \
207 } while(false)
208 
209 } // namespace cuda
210 
211 #endif // CUDA_API_WRAPPERS_RTC_ERROR_HPP_
Definitions and functionality wrapping CUDA APIs.
Definition: array.hpp:22
constexpr bool is_failure(status_t status)
Determine whether the API call returning the specified status had failed.
Definition: error.hpp:209
typename detail_::types< Kind >::status_type status_t
Status values returned by the NVIDIA run-time compilation libraries&#39;s API calls: The NVRTC library fo...
Definition: types.hpp:131
void throw_if_error(status_t status, const ::std::string &message) noexcept(false)
Do nothing...
Definition: error.hpp:335
status_t< Kind > code() const
Obtain the CUDA status code which resulted in this error being thrown.
Definition: error.hpp:154
Type definitions used in CUDA real-time compilation work wrappers.
inline ::std::string describe(status_t status)
Obtain a brief textual explanation for a specified kind of CUDA Runtime API status or error code...
Definition: error.hpp:215
bool operator==(const context_t &lhs, const context_t &rhs) noexcept
Definition: context.hpp:762
A (base?) class for exceptions raised by CUDA code; these errors are thrown by essentially all CUDA R...
Definition: error.hpp:123
constexpr bool is_success(status_t status)
Determine whether the API call returning the specified status had succeeded.
Definition: error.hpp:203
typename rtc::detail_::types< Kind >::named_status named_t
Aliases for NVRTC / PTX compilation library status codes.
Definition: error.hpp:42
CUresult status_t
Indicates either the result (success or error index) of a CUDA Runtime or Driver API call...
Definition: types.hpp:77