cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
error.hpp
Go to the documentation of this file.
1 
16 #pragma once
17 #ifndef CUDA_API_WRAPPERS_ERROR_HPP_
18 #define CUDA_API_WRAPPERS_ERROR_HPP_
19 
20 #include "types.hpp"
21 #include <cuda_runtime_api.h>
22 
23 #include <type_traits>
24 #include <string>
25 #include <stdexcept>
26 
27 namespace cuda {
28 
29 namespace status {
30 
36 enum named_t : ::std::underlying_type<status_t>::type {
37  success = CUDA_SUCCESS,
38  memory_allocation_failure = CUDA_ERROR_OUT_OF_MEMORY, // corresponds to cudaErrorMemoryAllocation
39  not_yet_initialized = CUDA_ERROR_NOT_INITIALIZED, // corresponds to cudaErrorInitializationError
40  already_deinitialized = CUDA_ERROR_DEINITIALIZED, // corresponds to cudaErrorCudartUnloading
41  profiler_disabled = CUDA_ERROR_PROFILER_DISABLED,
42 #if CUDA_VERSION >= 10100
43  profiler_not_initialized = CUDA_ERROR_PROFILER_NOT_INITIALIZED,
44 #endif
45  profiler_already_started = CUDA_ERROR_PROFILER_ALREADY_STARTED,
46  profiler_already_stopped = CUDA_ERROR_PROFILER_ALREADY_STOPPED,
47 #if CUDA_VERSION >= 11100
48  stub_library = CUDA_ERROR_STUB_LIBRARY,
49  device_not_licensed = CUDA_ERROR_DEVICE_NOT_LICENSED,
50 #endif
51  prior_launch_failure = cudaErrorPriorLaunchFailure,
52  launch_timeout = CUDA_ERROR_LAUNCH_TIMEOUT,
53  launch_out_of_resources = CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES,
54  kernel_launch_incompatible_texturing_mode = CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING,
55  invalid_kernel_function = cudaErrorInvalidDeviceFunction,
56  invalid_configuration = cudaErrorInvalidConfiguration,
57  invalid_device = CUDA_ERROR_INVALID_DEVICE,
58  invalid_value = CUDA_ERROR_INVALID_VALUE,
59  invalid_pitch_value = cudaErrorInvalidPitchValue,
60  invalid_symbol = cudaErrorInvalidSymbol,
61  map_buffer_object_failed = CUDA_ERROR_MAP_FAILED, // corresponds to cudaErrorMapBufferObjectFailed,
62  unmap_buffer_object_failed = CUDA_ERROR_UNMAP_FAILED, // corresponds to cudaErrorUnmapBufferObjectFailed,
63  array_still_mapped = CUDA_ERROR_ARRAY_IS_MAPPED,
64  resource_already_mapped = CUDA_ERROR_ALREADY_MAPPED,
65  resource_already_acquired = CUDA_ERROR_ALREADY_ACQUIRED,
66  resource_not_mapped = CUDA_ERROR_NOT_MAPPED,
67  not_mapped_as_pointer = CUDA_ERROR_NOT_MAPPED_AS_POINTER,
68  not_mapped_as_array = CUDA_ERROR_NOT_MAPPED_AS_ARRAY,
69  invalid_host_pointer = cudaErrorInvalidHostPointer,
70  invalid_device_pointer = cudaErrorInvalidDevicePointer,
71  invalid_texture = cudaErrorInvalidTexture,
72  invalid_texture_binding = cudaErrorInvalidTextureBinding,
73  invalid_channel_descriptor = cudaErrorInvalidChannelDescriptor,
74  invalid_memcpy_direction = cudaErrorInvalidMemcpyDirection,
75  address_of_constant = cudaErrorAddressOfConstant,
76  texture_fetch_failed = cudaErrorTextureFetchFailed,
77  texture_not_bound = cudaErrorTextureNotBound,
78  synchronization_error = cudaErrorSynchronizationError,
79  invalid_filter_setting = cudaErrorInvalidFilterSetting,
80  invalid_norm_setting = cudaErrorInvalidNormSetting,
81  mixed_device_execution = cudaErrorMixedDeviceExecution,
82  unknown = CUDA_ERROR_UNKNOWN,
83  not_yet_implemented = cudaErrorNotYetImplemented,
84  memory_value_too_large = cudaErrorMemoryValueTooLarge,
85  invalid_resource_handle = CUDA_ERROR_INVALID_HANDLE,
86 #if CUDA_VERSION >= 10000
87  resource_not_in_valid_state = CUDA_ERROR_ILLEGAL_STATE,
88 #endif
89  async_operations_not_yet_completed = CUDA_ERROR_NOT_READY,
90  insufficient_driver = cudaErrorInsufficientDriver,
91  set_on_active_process = cudaErrorSetOnActiveProcess,
92  invalid_surface = cudaErrorInvalidSurface,
93  symbol_not_found = CUDA_ERROR_NOT_FOUND, // corresponds to cudaErrorSymbolNotFound
94  no_device = CUDA_ERROR_NO_DEVICE,
95  ecc_uncorrectable = CUDA_ERROR_ECC_UNCORRECTABLE,
96  shared_object_symbol_not_found = CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND,
97  invalid_source = CUDA_ERROR_INVALID_SOURCE,
98  file_not_found = CUDA_ERROR_FILE_NOT_FOUND,
99  shared_object_init_failed = CUDA_ERROR_SHARED_OBJECT_INIT_FAILED,
100  jit_compiler_not_found = CUDA_ERROR_JIT_COMPILER_NOT_FOUND,
101 #if CUDA_VERSION >= 11100
102  unsupported_ptx_version = CUDA_ERROR_UNSUPPORTED_PTX_VERSION,
103 #endif
104 #if CUDA_VERSION >= 11200
105  jit_compilation_disabled = CUDA_ERROR_JIT_COMPILATION_DISABLED,
106 #endif
107 #if CUDA_VERSION >= 11400
108  unsupported_exec_affinity = CUDA_ERROR_UNSUPPORTED_EXEC_AFFINITY,
109 #endif
110  unsupported_limit = CUDA_ERROR_UNSUPPORTED_LIMIT,
111  duplicate_variable_name = cudaErrorDuplicateVariableName,
112  duplicate_texture_name = cudaErrorDuplicateTextureName,
113  duplicate_surface_name = cudaErrorDuplicateSurfaceName,
114  devices_unavailable = cudaErrorDevicesUnavailable,
115  invalid_kernel_image = CUDA_ERROR_INVALID_IMAGE, // corresponds to cudaErrorInvalidKernelImage,
116  no_kernel_image_for_device = CUDA_ERROR_NO_BINARY_FOR_GPU, // corresponds to cudaErrorNoKernelImageForDevice,
117  incompatible_driver_context = cudaErrorIncompatibleDriverContext,
118  missing_configuration = cudaErrorMissingConfiguration,
119  invalid_context = CUDA_ERROR_INVALID_CONTEXT,
120  context_already_current = CUDA_ERROR_CONTEXT_ALREADY_CURRENT,
121  context_already_in_use = CUDA_ERROR_CONTEXT_ALREADY_IN_USE,
122  peer_access_already_enabled = CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED,
123  peer_access_not_enabled = CUDA_ERROR_PEER_ACCESS_NOT_ENABLED,
124  device_already_in_use = cudaErrorDeviceAlreadyInUse,
125  primary_context_already_active = CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE,
126  context_is_destroyed = CUDA_ERROR_CONTEXT_IS_DESTROYED,
127  primary_context_is_uninitialized = CUDA_ERROR_CONTEXT_IS_DESTROYED, // an alias!
128 #if CUDA_VERSION >= 10200
129  device_uninitialized = cudaErrorDeviceUninitialized,
130 #endif
131  assert = CUDA_ERROR_ASSERT,
132  too_many_peers = CUDA_ERROR_TOO_MANY_PEERS,
133  host_memory_already_registered = CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED,
134  host_memory_not_registered = CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED,
135  operating_system = CUDA_ERROR_OPERATING_SYSTEM,
136  peer_access_unsupported = CUDA_ERROR_PEER_ACCESS_UNSUPPORTED,
137  launch_max_depth_exceeded = cudaErrorLaunchMaxDepthExceeded,
138  launch_file_scoped_tex = cudaErrorLaunchFileScopedTex,
139  launch_file_scoped_surf = cudaErrorLaunchFileScopedSurf,
140  sync_depth_exceeded = cudaErrorSyncDepthExceeded,
141  launch_pending_count_exceeded = cudaErrorLaunchPendingCountExceeded,
142  invalid_device_function = cudaErrorInvalidDeviceFunction,
143  not_permitted = CUDA_ERROR_NOT_PERMITTED,
144  not_supported = CUDA_ERROR_NOT_SUPPORTED,
145  hardware_stack_error = CUDA_ERROR_HARDWARE_STACK_ERROR,
146  illegal_instruction = CUDA_ERROR_ILLEGAL_INSTRUCTION,
147  misaligned_address = CUDA_ERROR_MISALIGNED_ADDRESS,
148  exception_during_kernel_execution = CUDA_ERROR_LAUNCH_FAILED,
149  cooperative_launch_too_large = CUDA_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE,
150  invalid_address_space = CUDA_ERROR_INVALID_ADDRESS_SPACE,
151  invalid_pc = CUDA_ERROR_INVALID_PC,
152  illegal_address = CUDA_ERROR_ILLEGAL_ADDRESS,
153  invalid_ptx = CUDA_ERROR_INVALID_PTX,
154  invalid_graphics_context = CUDA_ERROR_INVALID_GRAPHICS_CONTEXT,
155  nvlink_uncorrectable = CUDA_ERROR_NVLINK_UNCORRECTABLE,
156  startup_failure = cudaErrorStartupFailure,
157  api_failure_base = cudaErrorApiFailureBase,
158 #if CUDA_VERSION >= 10000
159  system_not_ready = CUDA_ERROR_SYSTEM_NOT_READY,
160  stream_capture_unsupported = CUDA_ERROR_STREAM_CAPTURE_UNSUPPORTED,
161  stream_capture_invalidated = CUDA_ERROR_STREAM_CAPTURE_INVALIDATED,
162  stream_capture_merge = CUDA_ERROR_STREAM_CAPTURE_MERGE,
163  stream_capture_unmatched = CUDA_ERROR_STREAM_CAPTURE_UNMATCHED,
164  stream_capture_unjoined = CUDA_ERROR_STREAM_CAPTURE_UNJOINED,
165  stream_capture_isolation = CUDA_ERROR_STREAM_CAPTURE_ISOLATION,
166  stream_capture_disallowed_implicit_dependency = CUDA_ERROR_STREAM_CAPTURE_IMPLICIT,
167  not_permitted_on_captured_event = CUDA_ERROR_CAPTURED_EVENT,
168 #endif
169 #if CUDA_VERSION >= 10100
170  system_driver_mismatch = CUDA_ERROR_SYSTEM_DRIVER_MISMATCH,
171  not_supported_on_device = CUDA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE,
172  stream_capture_wrong_thread = CUDA_ERROR_STREAM_CAPTURE_WRONG_THREAD,
173 #endif
174 #if CUDA_VERSION >= 10200
175  timeout_lapsed = CUDA_ERROR_TIMEOUT,
176  graph_update_would_violate_constraints = CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE,
177 #endif
178 #if CUDA_VERSION >= 11400
179  mps_connection_failed = CUDA_ERROR_MPS_CONNECTION_FAILED,
180  mps_rpc_failure = CUDA_ERROR_MPS_RPC_FAILURE,
181  mps_server_not_ready = CUDA_ERROR_MPS_SERVER_NOT_READY,
182  mps_max_clients_reached = CUDA_ERROR_MPS_MAX_CLIENTS_REACHED,
183  mps_max_connections_reached = CUDA_ERROR_MPS_MAX_CONNECTIONS_REACHED,
184  async_error_in_external_device = CUDA_ERROR_EXTERNAL_DEVICE,
185 #endif // CUDA_VERSION >= 11400
186 #if CUDA_VERSION >= 12000
187  invalid_cluster_size = CUDA_ERROR_INVALID_CLUSTER_SIZE,
188 #endif // CUDA_VERSION >= 12000
189 #if CUDA_VERSION >= 12040
190  necessary_function_not_loaded = CUDA_ERROR_FUNCTION_NOT_LOADED,
191  invalid_resource_type = CUDA_ERROR_INVALID_RESOURCE_TYPE,
192  resources_insufficient_or_inapplicable
193  = CUDA_ERROR_INVALID_RESOURCE_CONFIGURATION,
194 #endif // CUDA_VERSION >= 12040
195 #if CUDA_VERSION >= 12080
196  key_rotation_sequence_failure = CUDA_ERROR_KEY_ROTATION,
197 #endif // CUDA_VERSION >= 12080
198 #if CUDA_VERSION >= 13010
199  not_permitted_on_detached_stream = CUDA_ERROR_STREAM_DETACHED,
200 #endif // CUDA_VERSION >= 13010
201 };
202 
204 constexpr inline bool operator==(const status_t& lhs, const named_t& rhs) noexcept { return lhs == static_cast<status_t>(rhs); }
205 constexpr inline bool operator!=(const status_t& lhs, const named_t& rhs) noexcept { return lhs != static_cast<status_t>(rhs); }
206 constexpr inline bool operator==(const named_t& lhs, const status_t& rhs) noexcept { return static_cast<status_t>(lhs) == rhs; }
207 constexpr inline bool operator!=(const named_t& lhs, const status_t& rhs) noexcept { return static_cast<status_t>(lhs) != rhs; }
209 
210 } // namespace status
211 
214 constexpr bool is_success(status_t status) { return status == static_cast<status_t>(status::success); }
215 constexpr bool is_success(cudaError_t status) { return static_cast<status_t>(status) == static_cast<status_t>(status::success); }
217 
220 constexpr bool is_failure(status_t status) { return not is_success(status); }
221 constexpr bool is_failure(cudaError_t status) { return is_failure(static_cast<status_t>(status)); }
223 
226 inline ::std::string describe(status_t status)
227 {
228  // Even though status_t aliases the driver's CUresult type, some values are actually
229  // runtime error codes. The driver will fail to identify them (they're luckily distinct),
230  // and we can't distinguish proper failure from the case of a Runtime-API-only error
231  // code - so we also try the runtime API.
232  const char* description;
233  auto description_lookup_status = cuGetErrorString(status, &description);
234  return (description_lookup_status == CUDA_SUCCESS) ?
235  description : cudaGetErrorString(static_cast<cudaError_t>(status));
236 }
237 inline ::std::string describe(cudaError_t status) { return cudaGetErrorString(status); }
239 
240 namespace detail_ {
241 
242 template <typename I, bool UpperCase = false>
243 ::std::string as_hex(I x)
244 {
245  static_assert(::std::is_unsigned<I>::value, "only signed representations are supported");
246  unsigned num_hex_digits = 2*sizeof(I);
247  if (x == 0) return "0x0";
248 
249  enum { bits_per_hex_digit = 4 }; // = log_2 of 16
250  static const char* digit_characters =
251  UpperCase ? "0123456789ABCDEF" : "0123456789abcdef" ;
252 
253  ::std::string result(num_hex_digits,'0');
254  for (unsigned digit_index = 0; digit_index < num_hex_digits ; digit_index++)
255  {
256  size_t bit_offset = (num_hex_digits - 1 - digit_index) * bits_per_hex_digit;
257  auto hexadecimal_digit = (x >> bit_offset) & 0xF;
258  result[digit_index] = digit_characters[hexadecimal_digit];
259  }
260  return "0x0" + result.substr(result.find_first_not_of('0'), ::std::string::npos);
261 }
262 
263 // TODO: Perhaps find a way to avoid the extra function, so that as_hex() can
264 // be called for pointer types as well? Would be easier with boost's uint<T>...
265 template <typename I, bool UpperCase = false>
266 inline ::std::string ptr_as_hex(const I* ptr)
267 {
268  return as_hex(reinterpret_cast<uintptr_t>(ptr));
269 }
270 
271 } // namespace detail_
272 
282 class runtime_error : public ::std::runtime_error {
283 public:
285  runtime_error(status_t error_code) :
286  ::std::runtime_error(describe(error_code)), code_(error_code)
287  { }
288  // I wonder if I should do this the other way around
289  runtime_error(status_t error_code, const ::std::string& what_arg) :
290  ::std::runtime_error(what_arg + ": " + describe(error_code)),
291  code_(error_code)
292  { }
293  // I wonder if I should do this the other way around
294  runtime_error(status_t error_code, ::std::string&& what_arg) :
295  runtime_error(error_code, what_arg)
296  { }
298  explicit runtime_error(status::named_t error_code) :
299  runtime_error(static_cast<status_t>(error_code)) { }
300  runtime_error(status::named_t error_code, const ::std::string& what_arg) :
301  runtime_error(static_cast<status_t>(error_code), what_arg) { }
302  runtime_error(status::named_t error_code, ::std::string&& what_arg) :
303  runtime_error(static_cast<status_t>(error_code), what_arg) { }
304 
305 protected:
306  runtime_error(status_t error_code, ::std::runtime_error&& err) :
307  ::std::runtime_error(::std::move(err)), code_(error_code)
308  { }
309 
310 public:
313  static runtime_error with_message_override(status_t error_code, ::std::string complete_what_arg)
314  {
315  return runtime_error(error_code, ::std::runtime_error(::std::move(complete_what_arg)));
316  }
317 
319  status_t code() const { return code_; }
320 
321 private:
322  status_t code_;
323 };
324 
327 #define throw_if_error_lazy(status__, ... ) \
328 do { \
329  const ::cuda::status_t tie_status__ = static_cast<::cuda::status_t>(status__); \
330  if (::cuda::is_failure(tie_status__)) { \
331  throw ::cuda::runtime_error(tie_status__, (__VA_ARGS__)); \
332  } \
333 } while(false)
334 
345 inline void throw_if_error(status_t status, const ::std::string& message) noexcept(false)
347 {
348  if (is_failure(status)) { throw runtime_error(status, message); }
349 }
350 
351 inline void throw_if_error(cudaError_t status, const ::std::string& message) noexcept(false)
352 {
353  throw_if_error(static_cast<status_t>(status), message);
354 }
355 
356 inline void throw_if_error(status_t status, ::std::string&& message) noexcept(false)
357 {
358  if (is_failure(status)) { throw runtime_error(status, message); }
359 }
360 
361 inline void throw_if_error(cudaError_t status, ::std::string&& message) noexcept(false)
362 {
363  return throw_if_error(static_cast<status_t>(status), message);
364 }
366 
376 inline void throw_if_error(status_t status) noexcept(false)
377 {
378  if (is_failure(status)) { throw runtime_error(status); }
379 }
380 
381 inline void throw_if_error(cudaError_t status) noexcept(false)
382 {
383  throw_if_error(static_cast<status_t>(status));
384 }
385 
386 enum : bool {
387  dont_clear_errors = false,
388  do_clear_errors = true
389 };
390 
391 namespace detail_ {
392 
393 namespace outstanding_runtime_error {
394 
400 inline status_t clear() noexcept
401 {
402  return static_cast<status_t>(cudaGetLastError());
403 }
404 
410 inline status_t get() noexcept
411 {
412  return static_cast<status_t>(cudaPeekAtLastError());
413 }
414 
415 } // namespace outstanding_runtime_error
416 } // namespace detail_
417 
425 namespace outstanding_error {
426 
431 inline status_t get(bool try_clearing = false) noexcept(true)
432 {
433  static constexpr const unsigned dummy_flags{0};
434  auto status = cuInit(dummy_flags);
435  if (not is_success(status)) { return status; }
436  return static_cast<status_t>(try_clearing ? cudaGetLastError() : cudaPeekAtLastError());
437 }
438 
449 inline void ensure_none(const ::std::string &message) noexcept(false)
450 {
451  auto status = get();
452  throw_if_error(status, message);
453 }
454 
461 inline void ensure_none(const char *message) noexcept(false)
462 {
463  return ensure_none(::std::string{message});
464 }
465 
475 inline void ensure_none() noexcept(false)
476 {
477  auto status = get();
478  throw_if_error(status);
479 }
480 
481 } // namespace outstanding_error
482 
483 // The following few functions are used in the error messages
484 // generated for exceptions thrown by various API wrappers.
485 
486 namespace device {
487 namespace detail_ {
488 inline ::std::string identify(device::id_t device_id)
489 {
490  return ::std::string("device ") + ::std::to_string(device_id);
491 }
492 } // namespace detail_
493 } // namespace device
494 
495 namespace context {
496 namespace detail_ {
497 
498 inline ::std::string identify(handle_t handle)
499 {
500  return "context " + cuda::detail_::ptr_as_hex(handle);
501 }
502 
503 inline ::std::string identify(handle_t handle, device::id_t device_id)
504 {
505  return identify(handle) + " on " + device::detail_::identify(device_id);
506 }
507 
508 } // namespace detail_
509 
510 namespace current {
511 namespace detail_ {
512 inline ::std::string identify(context::handle_t handle)
513 {
514  return "current context: " + context::detail_::identify(handle);
515 }
516 inline ::std::string identify(context::handle_t handle, device::id_t device_id)
517 {
518  return "current context: " + context::detail_::identify(handle, device_id);
519 }
520 } // namespace detail_
521 } // namespace current
522 
523 } // namespace context
524 
525 namespace device {
526 namespace primary_context {
527 namespace detail_ {
528 
529 inline ::std::string identify(handle_t handle, device::id_t device_id)
530 {
531  return "context " + context::detail_::identify(handle, device_id);
532 }
533 inline ::std::string identify(handle_t handle)
534 {
535  return "context " + context::detail_::identify(handle);
536 }
537 } // namespace detail_
538 } // namespace primary_context
539 } // namespace device
540 
541 namespace stream {
542 namespace detail_ {
543 inline ::std::string identify(handle_t handle)
544 {
545  return "stream " + cuda::detail_::ptr_as_hex(handle);
546 }
547 inline ::std::string identify(handle_t handle, device::id_t device_id)
548 {
549  return identify(handle) + " on " + device::detail_::identify(device_id);
550 }
551 inline ::std::string identify(handle_t handle, context::handle_t context_handle)
552 {
553  return identify(handle) + " in " + context::detail_::identify(context_handle);
554 }
555 inline ::std::string identify(handle_t handle, context::handle_t context_handle, device::id_t device_id)
556 {
557  return identify(handle) + " in " + context::detail_::identify(context_handle, device_id);
558 }
559 } // namespace detail_
560 } // namespace stream
561 
562 namespace event {
563 namespace detail_ {
564 inline ::std::string identify(handle_t handle)
565 {
566  return "event " + cuda::detail_::ptr_as_hex(handle);
567 }
568 inline ::std::string identify(handle_t handle, device::id_t device_id)
569 {
570  return identify(handle) + " on " + device::detail_::identify(device_id);
571 }
572 inline ::std::string identify(handle_t handle, context::handle_t context_handle)
573 {
574  return identify(handle) + " on " + context::detail_::identify(context_handle);
575 }
576 inline ::std::string identify(handle_t handle, context::handle_t context_handle, device::id_t device_id)
577 {
578  return identify(handle) + " on " + context::detail_::identify(context_handle, device_id);
579 }
580 } // namespace detail_
581 } // namespace event
582 
583 namespace kernel {
584 namespace detail_ {
585 
586 inline ::std::string identify(const void* ptr)
587 {
588  return "kernel " + cuda::detail_::ptr_as_hex(ptr);
589 }
590 inline ::std::string identify(const void* ptr, device::id_t device_id)
591 {
592  return identify(ptr) + " on " + device::detail_::identify(device_id);
593 }
594 inline ::std::string identify(const void* ptr, context::handle_t context_handle)
595 {
596  return identify(ptr) + " in " + context::detail_::identify(context_handle);
597 }
598 inline ::std::string identify(const void* ptr, context::handle_t context_handle, device::id_t device_id)
599 {
600  return identify(ptr) + " in " + context::detail_::identify(context_handle, device_id);
601 }
602 inline ::std::string identify(handle_t handle)
603 {
604  return "kernel at " + cuda::detail_::ptr_as_hex(handle);
605 }
606 inline ::std::string identify(handle_t handle, context::handle_t context_handle)
607 {
608  return identify(handle) + " in " + context::detail_::identify(context_handle);
609 }
610 inline ::std::string identify(handle_t handle, device::id_t device_id)
611 {
612  return identify(handle) + " on " + device::detail_::identify(device_id);
613 }
614 inline ::std::string identify(handle_t handle, context::handle_t context_handle, device::id_t device_id)
615 {
616  return identify(handle) + " in " + context::detail_::identify(context_handle, device_id);
617 }
618 
619 } // namespace detail_
620 } // namespace kernel
621 
622 namespace memory {
623 namespace detail_ {
624 
625 inline ::std::string identify(region_t region)
626 {
627  return ::std::string("memory region at ") + cuda::detail_::ptr_as_hex(region.data())
628  + " of size " + ::std::to_string(region.size());
629 }
630 
631 inline ::std::string identify(location_t location)
632 {
633  switch (location.type) {
634  case CU_MEM_LOCATION_TYPE_DEVICE:
635  if (location.id != CU_DEVICE_CPU) {
636  return "global memory of " + cuda::device::detail_::identify(location.id);
637  }
638  // fallthrough
639  case CU_MEM_LOCATION_TYPE_HOST:
640  return "host (system) memory";
641  case CU_MEM_LOCATION_TYPE_HOST_NUMA:
642  return "host (system) NUMA node " + ::std::to_string(location.id);
643  case CU_MEM_LOCATION_TYPE_HOST_NUMA_CURRENT:
644  return "current host (system) NUMA node ";
645  default:
646  return "(invalid)";
647  }
648 }
649 
650 } // namespace detail_
651 
652 } // namespace memory
653 
654 } // namespace cuda
655 
656 #endif // CUDA_API_WRAPPERS_ERROR_HPP_
static runtime_error with_message_override(status_t error_code, ::std::string complete_what_arg)
Construct a runtime error which will not produce the default description for the error code...
Definition: error.hpp:313
Definitions and functionality wrapping CUDA APIs.
Definition: array.hpp:22
detail_::region_helper< memory::region_t > region_t
A child class of the generic region_t with some managed-memory-specific functionality.
Definition: memory.hpp:1974
void ensure_none() noexcept(false)
Does nothing (except possibly throwing an exception)
Definition: error.hpp:475
CUcontext handle_t
Raw CUDA driver handle for a context; see {context_t}.
Definition: types.hpp:880
Operation was successful; no errors.
Definition: error.hpp:38
constexpr bool is_failure(status_t status)
Determine whether the API call returning the specified status had failed.
Definition: error.hpp:220
CUmemLocation location_t
Used in a limited number of API functions which can relate both to CUDA device memory and system memo...
Definition: types.hpp:555
CUdevice id_t
Numeric ID of a CUDA device used by the CUDA Runtime API.
Definition: types.hpp:852
void throw_if_error(status_t status, const ::std::string &message) noexcept(false)
Do nothing...
Definition: error.hpp:346
named_t
Aliases for CUDA status codes.
Definition: error.hpp:36
A (base?) class for exceptions raised by CUDA code; these errors are thrown by essentially all CUDA R...
Definition: error.hpp:282
status_t code() const
Obtain the CUDA status code which resulted in this error being thrown.
Definition: error.hpp:319
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:226
bool operator==(const context_t &lhs, const context_t &rhs) noexcept
Definition: context.hpp:768
CUarray handle_t
Raw CUDA driver handle for arrays (of any dimension)
Definition: array.hpp:34
Fundamental CUDA-related type definitions.
constexpr bool is_success(status_t status)
Determine whether the API call returning the specified status had succeeded.
Definition: error.hpp:214
CUresult status_t
Indicates either the result (success or error index) of a CUDA Runtime or Driver API call...
Definition: types.hpp:74