Celeritas
0.5.0-86+4a8eea4
|
Macros, exceptions, and helpers for assertions and error handling. More...
#include <stdexcept>
#include <string>
#include <ostream>
#include <sstream>
#include "corecel/Config.hh"
#include "Macros.hh"
Classes | |
struct | celeritas::DebugErrorDetails |
Detailed properties of a debug assertion failure. More... | |
struct | celeritas::RuntimeErrorDetails |
Detailed properties of a runtime error. More... | |
class | celeritas::DebugError |
Error thrown by Celeritas assertions. More... | |
class | celeritas::RuntimeError |
Error thrown by working code from unexpected runtime conditions. More... | |
class | celeritas::RichContextException |
Base class for writing arbitrary exception context to JSON. More... | |
Macros | |
#define | CELER_DEBUG_FAIL(MSG, WHICH) |
Throw a debug assertion regardless of the CELERITAS_DEBUG setting. More... | |
#define | CELER_RUNTIME_THROW(WHICH, WHAT, COND) |
#define | CELER_EXPECT(COND) CELER_NOASSERT_(COND) |
Precondition debug assertion macro. More... | |
#define | CELER_ASSERT(COND) CELER_NOASSERT_(COND) |
Internal debug assertion macro. More... | |
#define | CELER_ENSURE(COND) CELER_NOASSERT_(COND) |
Postcondition debug assertion macro. More... | |
#define | CELER_ASSUME(COND) CELER_NDEBUG_ASSUME_(COND) |
Always-on compiler assumption. More... | |
#define | CELER_ASSERT_UNREACHABLE() ::celeritas::unreachable() |
Throw an assertion if the code point is reached. More... | |
#define | CELER_VALIDATE(COND, MSG) |
Always-on runtime assertion macro. More... | |
#define | CELER_NOT_CONFIGURED(WHAT) |
Assert if the code point is reached because an optional feature is disabled. More... | |
#define | CELER_NOT_IMPLEMENTED(WHAT) CELER_RUNTIME_THROW(::celeritas::RuntimeError::not_impl_err_str, WHAT, {}) |
Assert if the code point is reached because a feature has yet to be fully implemented. More... | |
#define | CELER_CUDA_CALL(STATEMENT) |
When CUDA support is enabled, execute the wrapped statement and throw a RuntimeError if it fails. More... | |
#define | CELER_HIP_CALL(STATEMENT) |
When HIP support is enabled, execute the wrapped statement and throw a RuntimeError if it fails. More... | |
#define | CELER_DEVICE_CALL_PREFIX(STMT) |
Prepend the argument with "cuda" or "hip" and call with the appropriate checking statement as above. More... | |
#define | CELER_DEVICE_CHECK_ERROR() CELER_DEVICE_CALL_PREFIX(PeekAtLastError()) |
After a kernel launch or other call, check that no CUDA errors have occurred. More... | |
#define | CELER_MPI_CALL(STATEMENT) |
When MPI support is enabled, execute the wrapped statement and throw a RuntimeError if it fails. More... | |
Enumerations | |
enum class | celeritas::DebugErrorType { precondition , internal , unreachable , postcondition , assumption } |
Functions | |
void | celeritas::unreachable () |
Invoke undefined behavior. | |
char const * | celeritas::to_cstring (DebugErrorType which) |
Get a human-readable string describing a debug error. | |
std::string | celeritas::mpi_error_to_string (int errorcode) |
Get an MPI error string. | |
Macros, exceptions, and helpers for assertions and error handling.
This defines host- and device-compatible assertion macros that are toggled on the CELERITAS_DEBUG
and CELERITAS_DEVICE_DEBUG
configure macros.
#define CELER_ASSERT | ( | COND | ) | CELER_NOASSERT_(COND) |
Internal debug assertion macro.
This replaces standard assert
usage.
#define CELER_ASSERT_UNREACHABLE | ( | ) | ::celeritas::unreachable() |
Throw an assertion if the code point is reached.
When debug assertions are turned off, this changes to a compiler hint that improves optimization (and may force the coded to exit uncermoniously if the point is encountered, rather than continuing on with undefined behavior).
#define CELER_ASSUME | ( | COND | ) | CELER_NDEBUG_ASSUME_(COND) |
Always-on compiler assumption.
This should be used very rarely: you should make sure the resulting assembly is simplified in optimize mode from using the assumption. For example, sometimes informing the compiler of an assumption can reduce code bloat by skipping standard library exception handling code (e.g. in std::visit
by assuming !var_obj
.valueless_by_exception() ).
#define CELER_CUDA_CALL | ( | STATEMENT | ) |
When CUDA support is enabled, execute the wrapped statement and throw a RuntimeError if it fails.
If CUDA is disabled, throw an unconfigured assertion.
If it fails, we call cudaGetLastError
to clear the error code. Note that this will not clear the code in a few fatal error cases (kernel assertion failure, invalid memory access) and all subsequent CUDA calls will fail.
corecel/DeviceRuntimeApi.hh
. #define CELER_DEBUG_FAIL | ( | MSG, | |
WHICH | |||
) |
Throw a debug assertion regardless of the CELERITAS_DEBUG
setting.
This is used internally but is also useful for catching subtle programming errors in downstream code.
#define CELER_DEVICE_CALL_PREFIX | ( | STMT | ) |
Prepend the argument with "cuda" or "hip" and call with the appropriate checking statement as above.
Example:
corecel/DeviceRuntimeApi.hh
. The CorecelDeviceRuntimeApiHh
declaration enforces this when CUDA/HIP are disabled. #define CELER_DEVICE_CHECK_ERROR | ( | ) | CELER_DEVICE_CALL_PREFIX(PeekAtLastError()) |
After a kernel launch or other call, check that no CUDA errors have occurred.
This is also useful for checking success after external CUDA libraries have been called.
#define CELER_ENSURE | ( | COND | ) | CELER_NOASSERT_(COND) |
Postcondition debug assertion macro.
Use to "ensure" that return values or side effects are as expected when leaving a function.
#define CELER_EXPECT | ( | COND | ) | CELER_NOASSERT_(COND) |
Precondition debug assertion macro.
We "expect" that the input values or initial state satisfy a precondition, and we throw exception in debug mode if they do not.
#define CELER_HIP_CALL | ( | STATEMENT | ) |
When HIP support is enabled, execute the wrapped statement and throw a RuntimeError if it fails.
If HIP is disabled, throw an unconfigured assertion.
If it fails, we call hipGetLastError
to clear the error code.
corecel/DeviceRuntimeApi.hh
. The CorecelDeviceRuntimeApiHh
declaration enforces this when HIP is disabled. #define CELER_MPI_CALL | ( | STATEMENT | ) |
When MPI support is enabled, execute the wrapped statement and throw a RuntimeError if it fails.
If MPI is disabled, throw an unconfigured assertion.
mpi.h
. #define CELER_NOT_CONFIGURED | ( | WHAT | ) |
Assert if the code point is reached because an optional feature is disabled.
This generally should be used for the constructors of dummy class definitions in, e.g., Foo.nocuda.cc
:
#define CELER_NOT_IMPLEMENTED | ( | WHAT | ) | CELER_RUNTIME_THROW(::celeritas::RuntimeError::not_impl_err_str, WHAT, {}) |
Assert if the code point is reached because a feature has yet to be fully implemented.
This placeholder is so that code paths can be "declared but not defined" and implementations safely postponed in a greppable manner. This should not be used to define "unused" overrides for virtual classes. A correct use case would be:
#define CELER_RUNTIME_THROW | ( | WHICH, | |
WHAT, | |||
COND | |||
) |
#define CELER_VALIDATE | ( | COND, | |
MSG | |||
) |
Always-on runtime assertion macro.
This can check user input and input data consistency, and will raise RuntimeError on failure with a descriptive error message that is streamed as the second argument. This macro cannot be used in device
-annotated code.
The error message should read:
"<PROBLEM> (<WHY IT'S A PROBLEM>) <SUGGESTION>?"
Examples with correct casing and punctuation:
This looks in pracice like:
An always-on debug-type assertion without a detailed message can be constructed by omitting the stream (but leaving the comma):
|
strong |