Skip to content

Commit

Permalink
Fixes #425: Now lazily constructing exception error messages:
Browse files Browse the repository at this point in the history
* Added `throw_if_error_lazy()`, a macro alternative to the `throw_if_error()` function, which constructs the message string only when actually throwing an error
* Using throw_if_error_lazy()` extensively in the API wrapper implementations
  • Loading branch information
eyalroz committed Oct 10, 2022
1 parent 10962e2 commit 1a055ca
Show file tree
Hide file tree
Showing 33 changed files with 173 additions and 165 deletions.
2 changes: 1 addition & 1 deletion src/cuda/api/apriori_compiled_kernel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ inline handle_t get_handle(const void *kernel_function_ptr, const char* name = n

handle_t handle;
auto status = cudaGetFuncBySymbol(&handle, kernel_function_ptr);
throw_if_error(status, "Failed obtaining a CUDA function handle for "
throw_if_error_lazy(status, "Failed obtaining a CUDA function handle for "
+ ((name == nullptr) ? ::std::string("a kernel function") : ::std::string("kernel function ") + name)
+ " at " + cuda::detail_::ptr_as_hex(kernel_function_ptr));
return handle;
Expand Down
8 changes: 4 additions & 4 deletions src/cuda/api/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ handle_t create_in_current_context(dimensions_t<3> dimensions)
descriptor.Flags = 0;

auto status = cuArray3DCreate(&handle, &descriptor);
throw_if_error(status, "failed allocating 3D CUDA array");
throw_if_error_lazy(status, "failed allocating 3D CUDA array");
return handle;
}

Expand All @@ -84,7 +84,7 @@ handle_t create_in_current_context(dimensions_t<2> dimensions)
descriptor.NumChannels = 1;
handle_t handle;
auto status = cuArrayCreate(&handle, &descriptor);
throw_if_error(status, "failed allocating 2D CUDA array");
throw_if_error_lazy(status, "failed allocating 2D CUDA array");
return handle;
}

Expand All @@ -106,7 +106,7 @@ handle_t get_descriptor(context::handle_t context_handle, handle_t handle)
auto status = (NumDimensions == 2) ?
cuArrayGetDescriptor(&result, handle) :
cuArray3DGetDescriptor(&result, handle);
throw_if_error(status,
throw_if_error_lazy(status,
::std::string("Failed obtaining the descriptor of the CUDA ") +
(NumDimensions == 2 ? "2":"3") + "D array at " + cuda::detail_::ptr_as_hex(handle));
return result;
Expand Down Expand Up @@ -170,7 +170,7 @@ class array_t {
auto status = cuArrayDestroy(handle_);
// Note: Throwing in a noexcept destructor; if the free'ing fails, the program
// will likely terminate
throw_if_error(status, "Failed destroying CUDA array " + cuda::detail_::ptr_as_hex(handle_));
throw_if_error_lazy(status, "Failed destroying CUDA array " + cuda::detail_::ptr_as_hex(handle_));
}
}

Expand Down
28 changes: 14 additions & 14 deletions src/cuda/api/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ inline limit_value_t get_limit(limit_t limit_id)
{
limit_value_t limit_value;
auto status = cuCtxGetLimit(&limit_value, limit_id);
throw_if_error(status,
throw_if_error_lazy(status,
"Failed obtaining CUDA context limit value");
return limit_value;
}

inline void set_limit(limit_t limit_id, limit_value_t new_value)
{
auto status = cuCtxSetLimit(limit_id, new_value);
throw_if_error(status, "Failed obtaining CUDA context limit value");
throw_if_error_lazy(status, "Failed obtaining CUDA context limit value");
}

constexpr flags_t inline make_flags(
Expand Down Expand Up @@ -122,7 +122,7 @@ inline size_t total_memory(handle_t handle)
{
size_t total_mem_in_bytes;
auto status = cuMemGetInfo(nullptr, &total_mem_in_bytes);
throw_if_error(status, "Failed determining amount of total memory for " + identify(handle));
throw_if_error_lazy(status, "Failed determining amount of total memory for " + identify(handle));
return total_mem_in_bytes;

}
Expand All @@ -131,14 +131,14 @@ inline size_t free_memory(handle_t handle)
{
size_t free_mem_in_bytes;
auto status = cuMemGetInfo(&free_mem_in_bytes, nullptr);
throw_if_error(status, "Failed determining amount of free memory for " + identify(handle));
throw_if_error_lazy(status, "Failed determining amount of free memory for " + identify(handle));
return free_mem_in_bytes;
}

inline void set_cache_preference(handle_t handle, multiprocessor_cache_preference_t preference)
{
auto status = cuCtxSetCacheConfig(static_cast<CUfunc_cache>(preference));
throw_if_error(status,
throw_if_error_lazy(status,
"Setting the multiprocessor L1/Shared Memory cache distribution preference to " +
::std::to_string((unsigned) preference) + " for " + identify(handle));
}
Expand All @@ -147,7 +147,7 @@ inline multiprocessor_cache_preference_t cache_preference(handle_t handle)
{
CUfunc_cache preference;
auto status = cuCtxGetCacheConfig(&preference);
throw_if_error(status,
throw_if_error_lazy(status,
"Obtaining the multiprocessor L1/Shared Memory cache distribution preference for " + identify(handle));
return (multiprocessor_cache_preference_t) preference;
}
Expand All @@ -156,14 +156,14 @@ inline shared_memory_bank_size_t shared_memory_bank_size(handle_t handle)
{
CUsharedconfig bank_size;
auto status = cuCtxGetSharedMemConfig(&bank_size);
throw_if_error(status, "Obtaining the multiprocessor shared memory bank size for " + identify(handle));
throw_if_error_lazy(status, "Obtaining the multiprocessor shared memory bank size for " + identify(handle));
return static_cast<shared_memory_bank_size_t>(bank_size);
}

inline void set_shared_memory_bank_size(handle_t handle, shared_memory_bank_size_t bank_size)
{
auto status = cuCtxSetSharedMemConfig(static_cast<CUsharedconfig>(bank_size));
throw_if_error(status, "Setting the multiprocessor shared memory bank size for " + identify(handle));
throw_if_error_lazy(status, "Setting the multiprocessor shared memory bank size for " + identify(handle));
}

inline void synchronize(context::handle_t handle)
Expand All @@ -181,13 +181,13 @@ inline void synchronize(device::id_t device_id, context::handle_t handle)
inline void destroy(handle_t handle)
{
auto status = cuCtxDestroy(handle);
throw_if_error(status, "Failed destroying " + identify(handle));
throw_if_error_lazy(status, "Failed destroying " + identify(handle));
}

inline void destroy(handle_t handle, device::id_t device_index)
{
auto status = cuCtxDestroy(handle);
throw_if_error(status, "Failed destroying " + identify(handle, device_index));
throw_if_error_lazy(status, "Failed destroying " + identify(handle, device_index));
}

inline context::flags_t get_flags(handle_t handle)
Expand Down Expand Up @@ -461,7 +461,7 @@ class context_t {
scoped_setter_type set_context_for_this_scope(handle_);
context::stream_priority_range_t result;
auto status = cuCtxGetStreamPriorityRange(&result.least, &result.greatest);
throw_if_error(status, "Obtaining the priority range for streams within " +
throw_if_error_lazy(status, "Obtaining the priority range for streams within " +
context::detail_::identify(*this));
return result;
}
Expand All @@ -476,7 +476,7 @@ class context_t {
{
unsigned int raw_version;
auto status = cuCtxGetApiVersion(handle_, &raw_version);
throw_if_error(status, "Failed obtaining the API version for " + context::detail_::identify(*this));
throw_if_error_lazy(status, "Failed obtaining the API version for " + context::detail_::identify(*this));
return version_t::from_single_number((int) raw_version);
}

Expand Down Expand Up @@ -540,7 +540,7 @@ class context_t {
scoped_setter_type set_context_for_this_scope(handle_);
#if (CUDA_VERSION >= 11000)
auto status = cuCtxResetPersistingL2Cache();
throw_if_error(status, "Failed resetting/clearing the persisting L2 cache memory");
throw_if_error_lazy(status, "Failed resetting/clearing the persisting L2 cache memory");
#endif
throw cuda::runtime_error(
cuda::status::insufficient_driver,
Expand Down Expand Up @@ -709,7 +709,7 @@ inline handle_t create_and_push(
keep_larger_local_mem_after_resize);
handle_t handle;
auto status = cuCtxCreate(&handle, flags, device_id);
throw_if_error(status, "failed creating a CUDA context associated with "
throw_if_error_lazy(status, "failed creating a CUDA context associated with "
+ device::detail_::identify(device_id));
return handle;
}
Expand Down
14 changes: 7 additions & 7 deletions src/cuda/api/current_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ inline bool exists()
if (status == cuda::status::not_yet_initialized) {
return false;
}
throw_if_error(status, "Failed obtaining the current context's handle");
throw_if_error_lazy(status, "Failed obtaining the current context's handle");
return (handle != context::detail_::none);
}

Expand Down Expand Up @@ -93,7 +93,7 @@ inline status_and_handle_pair get_with_status()
inline handle_t get_handle()
{
auto p = get_with_status();
throw_if_error(p.status, "Failed obtaining the current context's handle");
throw_if_error_lazy(p.status, "Failed obtaining the current context's handle");
return p.handle;
}

Expand All @@ -102,15 +102,15 @@ inline context::flags_t get_flags()
{
context::flags_t result;
auto status = cuCtxGetFlags(&result);
throw_if_error(status, "Failed obtaining the current context's flags");
throw_if_error_lazy(status, "Failed obtaining the current context's flags");
return result;
}

inline device::id_t get_device_id()
{
device::id_t device_id;
auto result = cuCtxGetDevice(&device_id);
throw_if_error(result, "Failed obtaining the current context's device");
throw_if_error_lazy(result, "Failed obtaining the current context's device");
return device_id;
}

Expand All @@ -125,7 +125,7 @@ inline device::id_t get_device_id()
inline void push(handle_t context_handle)
{
auto status = cuCtxPushCurrent(context_handle);
throw_if_error(status, "Failed pushing to the top of the context stack: "
throw_if_error_lazy(status, "Failed pushing to the top of the context stack: "
+ context::detail_::identify(context_handle));
}

Expand All @@ -152,7 +152,7 @@ inline context::handle_t pop()
{
handle_t popped_context_handle;
auto status = cuCtxPopCurrent(&popped_context_handle);
throw_if_error(status, "Failed popping the current CUDA context");
throw_if_error_lazy(status, "Failed popping the current CUDA context");
return popped_context_handle;
}

Expand All @@ -162,7 +162,7 @@ inline void set(handle_t context_handle)
// if (detail_::get_handle() == context_handle_) { return; }
// ... but decided against it.
auto status = cuCtxSetCurrent(context_handle);
throw_if_error(status,
throw_if_error_lazy(status,
"Failed setting the current context to " + context::detail_::identify(context_handle));
}

Expand Down
6 changes: 3 additions & 3 deletions src/cuda/api/current_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ inline id_t get_id()
// Should we activate and push the default device's context? probably not.
return default_device_id;
}
throw_if_error(status,
throw_if_error_lazy(status,
"Failed obtaining the current context for determining which device is active");

if (current_context_handle == context::detail_::none) {
Expand All @@ -64,7 +64,7 @@ inline id_t get_id()
//
// handle_t device_id;
// auto status = cudaGetDevice(&device_id);
// throw_if_error(status, "Failure obtaining current device id");
// throw_if_error_lazy(status, "Failure obtaining current device id");
// return device_id;
}

Expand Down Expand Up @@ -154,7 +154,7 @@ inline void set(const id_t *device_ids, size_t num_devices)
throw cuda::runtime_error(status::invalid_device, "More devices listed than exist on the system");
}
auto result = cudaSetValidDevices(const_cast<int *>(device_ids), (int) num_devices);
throw_if_error(result,
throw_if_error_lazy(result,
"Failure setting the current device to any of the list of "
+ ::std::to_string(num_devices) + " devices specified");
}
Expand Down
16 changes: 8 additions & 8 deletions src/cuda/api/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ inline ::std::string get_name(id_t id)
auto buffer_size = (size_type) (sizeof(stack_buffer) / sizeof(char));
auto try_getting_name = [&](char* buffer, size_type buffer_size) -> size_type {
auto status = cuDeviceGetName(buffer, buffer_size-1, id);
throw_if_error(status, "Failed obtaining the CUDA device name");
throw_if_error_lazy(status, "Failed obtaining the CUDA device name");
buffer[buffer_size-1] = '\0';
return (size_type) ::std::strlen(buffer);
};
Expand Down Expand Up @@ -163,7 +163,7 @@ class device_t {
context_setter_type set_for_this_scope(primary_context_handle());
int result;
auto status = cuDeviceCanAccessPeer(&result, id(), peer.id());
throw_if_error(status, "Failed determining whether "
throw_if_error_lazy(status, "Failed determining whether "
+ device::detail_::identify(id_) + " can access "
+ device::detail_::identify(peer.id_));
return (result == 1);
Expand Down Expand Up @@ -194,7 +194,7 @@ class device_t {
uuid_t uuid () const {
uuid_t result;
auto status = cuDeviceGetUuid(&result, id_);
throw_if_error(status, "Failed obtaining UUID for " + device::detail_::identify(id_));
throw_if_error_lazy(status, "Failed obtaining UUID for " + device::detail_::identify(id_));
return result;
}
#endif // CUDA_VERSION >= 9020
Expand Down Expand Up @@ -228,7 +228,7 @@ class device_t {
void set_flags(flags_type new_flags) const
{
auto status = cuDevicePrimaryCtxSetFlags(id(), new_flags);
throw_if_error(status, "Failed setting (primary context) flags for device " + device::detail_::identify(id_));
throw_if_error_lazy(status, "Failed setting (primary context) flags for device " + device::detail_::identify(id_));
}

public:
Expand All @@ -242,14 +242,14 @@ class device_t {
{
properties_t properties;
auto status = cudaGetDeviceProperties(&properties, id());
throw_if_error(status, "Failed obtaining device properties for " + device::detail_::identify(id_));
throw_if_error_lazy(status, "Failed obtaining device properties for " + device::detail_::identify(id_));
return properties;
}

static device_t choose_best_match(const properties_t& properties) {
device::id_t id;
auto status = cudaChooseDevice(&id, &properties);
throw_if_error(status, "Failed choosing a best matching device by a a property set.");
throw_if_error_lazy(status, "Failed choosing a best matching device by a a property set.");
return device::wrap(id);
}

Expand All @@ -274,7 +274,7 @@ class device_t {
{
attribute_value_t attribute_value;
auto status = cuDeviceGetAttribute(&attribute_value, attribute, id_);
throw_if_error(status, "Failed obtaining device properties for " + device::detail_::identify(id_));
throw_if_error_lazy(status, "Failed obtaining device properties for " + device::detail_::identify(id_));
return attribute_value;
}

Expand Down Expand Up @@ -428,7 +428,7 @@ class device_t {
primary_context_handle_;
context_setter_type set_context_for_this_scope{pc_handle};
auto status = cudaDeviceReset();
throw_if_error(status, "Resetting " + device::detail_::identify(id_));
throw_if_error_lazy(status, "Resetting " + device::detail_::identify(id_));
}

/**
Expand Down
8 changes: 8 additions & 0 deletions src/cuda/api/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,14 @@ class runtime_error : public ::std::runtime_error {
status_t code_;
};

#define throw_if_error_lazy(status__, ... ) \
do { \
status_t tie_status__ = static_cast<status_t>(status__); \
if (is_failure(tie_status__)) { \
throw runtime_error(tie_status__, (__VA_ARGS__)); \
} \
} while(false)

// TODO: The following could use ::std::optional arguments - which would
// prevent the need for dual versions of the functions - but we're
// not writing C++17 here
Expand Down
10 changes: 5 additions & 5 deletions src/cuda/api/event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ inline void destroy(
inline void enqueue_in_current_context(stream::handle_t stream_handle, handle_t event_handle)
{
auto status = cuEventRecord(event_handle, stream_handle);
throw_if_error(status,
throw_if_error_lazy(status,
"Failed recording " + event::detail_::identify(event_handle)
+ " on " + stream::detail_::identify(stream_handle));
}
Expand Down Expand Up @@ -342,7 +342,7 @@ inline duration_t time_elapsed_between(const event_t& start, const event_t& end)
{
float elapsed_milliseconds;
auto status = cuEventElapsedTime(&elapsed_milliseconds, start.handle(), end.handle());
throw_if_error(status, "determining the time elapsed between events");
throw_if_error_lazy(status, "determining the time elapsed between events");
return duration_t { elapsed_milliseconds };
}

Expand Down Expand Up @@ -372,7 +372,7 @@ inline handle_t create_raw_in_current_context(flags_t flags = 0u)
{
cuda::event::handle_t new_event_handle;
auto status = cuEventCreate(&new_event_handle, flags);
throw_if_error(status, "Failed creating a CUDA event");
throw_if_error_lazy(status, "Failed creating a CUDA event");
return new_event_handle;
}

Expand Down Expand Up @@ -401,7 +401,7 @@ inline void destroy_in_current_context(
context::handle_t current_context_handle)
{
auto status = cuEventDestroy(handle);
throw_if_error(status, "Failed destroying " +
throw_if_error_lazy(status, "Failed destroying " +
identify(handle, current_context_handle, current_device_id));
}

Expand Down Expand Up @@ -478,7 +478,7 @@ inline void wait(event_t event)
auto event_handle = event.handle();
context::current::detail_::scoped_override_t context_for_this_scope(context_handle);
auto status = cuEventSynchronize(event_handle);
throw_if_error(status, "Failed synchronizing " + event::detail_::identify(event));
throw_if_error_lazy(status, "Failed synchronizing " + event::detail_::identify(event));
}

inline void synchronize(event_t event)
Expand Down
Loading

0 comments on commit 1a055ca

Please sign in to comment.