Spaces:
Running
Running
namespace c10 { | |
/// The primary ATen error class. | |
/// Provides a complete error message with source location information via | |
/// `what()`, and a more concise message via `what_without_backtrace()`. | |
/// Don't throw this directly; use TORCH_CHECK/TORCH_INTERNAL_ASSERT instead. | |
/// | |
/// NB: c10::Error is handled specially by the default torch to suppress the | |
/// backtrace, see torch/csrc/Exceptions.h | |
class C10_API Error : public std::exception { | |
// The actual error message. | |
std::string msg_; | |
// Context for the message (in order of decreasing specificity). Context will | |
// be automatically formatted appropriately, so it is not necessary to add | |
// extra leading/trailing newlines to strings inside this vector | |
std::vector<std::string> context_; | |
// The C++ backtrace at the point when this exception was raised. This | |
// may be empty if there is no valid backtrace. (We don't use optional | |
// here to reduce the dependencies this file has.) | |
std::string backtrace_; | |
// These two are derived fields from msg_stack_ and backtrace_, but we need | |
// fields for the strings so that we can return a const char* (as the | |
// signature of std::exception requires). Currently, the invariant | |
// is that these fields are ALWAYS populated consistently with respect | |
// to msg_stack_ and backtrace_. | |
std::string what_; | |
std::string what_without_backtrace_; | |
// This is a little debugging trick: you can stash a relevant pointer | |
// in caller, and then when you catch the exception, you can compare | |
// against pointers you have on hand to get more information about | |
// where the exception came from. In Caffe2, this is used to figure | |
// out which operator raised an exception. | |
const void* caller_; | |
public: | |
// PyTorch-style Error constructor. NB: the implementation of this | |
// is actually in Logging.cpp | |
Error(SourceLocation source_location, std::string msg); | |
// Caffe2-style error message | |
Error( | |
const char* file, | |
const uint32_t line, | |
const char* condition, | |
const std::string& msg, | |
const std::string& backtrace, | |
const void* caller = nullptr); | |
// Base constructor | |
Error(std::string msg, std::string backtrace, const void* caller = nullptr); | |
// Add some new context to the message stack. The last added context | |
// will be formatted at the end of the context list upon printing. | |
// WARNING: This method is O(n) in the size of the stack, so don't go | |
// wild adding a ridiculous amount of context to error messages. | |
void add_context(std::string msg); | |
const std::string& msg() const { | |
return msg_; | |
} | |
const std::vector<std::string>& context() const { | |
return context_; | |
} | |
const std::string& backtrace() const { | |
return backtrace_; | |
} | |
/// Returns the complete error message, including the source location. | |
/// The returned pointer is invalidated if you call add_context() on | |
/// this object. | |
const char* what() const noexcept override { | |
return what_.c_str(); | |
} | |
const void* caller() const noexcept { | |
return caller_; | |
} | |
/// Returns only the error message string, without source location. | |
/// The returned pointer is invalidated if you call add_context() on | |
/// this object. | |
virtual const char* what_without_backtrace() const noexcept { | |
return what_without_backtrace_.c_str(); | |
} | |
private: | |
void refresh_what(); | |
std::string compute_what(bool include_backtrace) const; | |
}; | |
class C10_API Warning { | |
public: | |
class C10_API UserWarning {}; | |
class C10_API DeprecationWarning {}; | |
using warning_variant_t = std::variant<UserWarning, DeprecationWarning>; | |
Warning( | |
warning_variant_t type, | |
const SourceLocation& source_location, | |
std::string msg, | |
bool verbatim); | |
Warning( | |
warning_variant_t type, | |
SourceLocation source_location, | |
const char* msg, | |
bool verbatim); | |
Warning( | |
warning_variant_t type, | |
SourceLocation source_location, | |
::c10::detail::CompileTimeEmptyString msg, | |
bool verbatim); | |
// Getters for members | |
warning_variant_t type() const; | |
const SourceLocation& source_location() const; | |
const std::string& msg() const; | |
bool verbatim() const; | |
private: | |
// The type of warning | |
warning_variant_t type_; | |
// Where the warning happened. | |
SourceLocation source_location_; | |
// The actual warning message. | |
std::string msg_; | |
// See note: [Verbatim Warnings] | |
bool verbatim_; | |
}; | |
using UserWarning = Warning::UserWarning; | |
using DeprecationWarning = Warning::DeprecationWarning; | |
// Issue a warning with a given message. Dispatched to the current | |
// warning handler. | |
void C10_API warn(const Warning& warning); | |
class C10_API WarningHandler { | |
public: | |
virtual ~WarningHandler() = default; | |
/// The default warning handler. Prints the message to stderr. | |
virtual void process(const Warning& warning); | |
}; | |
namespace WarningUtils { | |
// Note: [Verbatim Warnings] | |
// Warnings originating in C++ code can appear out-of-place to Python users: | |
// a user runs a line in Python, but the warning references a line in C++. | |
// Some parts of PyTorch, like the JIT, are cognizant of this mismatch | |
// and take care to map warnings back to the user's program, but most | |
// of PyTorch simply throws a context-free warning. To allow warning | |
// handlers to add context where appropriate, warn takes the | |
// "verbatim" flag. When this is false a warning handler might append | |
// the C++ warning to a Python warning message that relates the warning | |
// back to the user's program. Callers who have already accounted for | |
// context in their warnings should set verbatim to true so their warnings | |
// appear without modification. | |
/// Sets the global warning handler. This is not thread-safe, so it should | |
/// generally be called once during initialization or while holding the GIL | |
/// for programs that use python. | |
/// User is responsible for keeping the WarningHandler alive until | |
/// it is not needed. | |
C10_API void set_warning_handler(WarningHandler* handler) noexcept(true); | |
/// Gets the global warning handler. | |
C10_API WarningHandler* get_warning_handler() noexcept(true); | |
class C10_API WarningHandlerGuard { | |
WarningHandler* prev_handler_; | |
public: | |
WarningHandlerGuard(WarningHandler* new_handler) | |
: prev_handler_(c10::WarningUtils::get_warning_handler()) { | |
c10::WarningUtils::set_warning_handler(new_handler); | |
} | |
~WarningHandlerGuard() { | |
c10::WarningUtils::set_warning_handler(prev_handler_); | |
} | |
}; | |
/// The TORCH_WARN_ONCE macro is difficult to test for. Use | |
/// setWarnAlways(true) to turn it into TORCH_WARN, which can be | |
/// tested for more easily. | |
C10_API void set_warnAlways(bool) noexcept(true); | |
C10_API bool get_warnAlways() noexcept(true); | |
// A RAII guard that sets warn_always (not thread-local) on | |
// construction, and sets it back to the original value upon destruction. | |
struct C10_API WarnAlways { | |
public: | |
explicit WarnAlways(bool setting = true); | |
~WarnAlways(); | |
private: | |
bool prev_setting; | |
}; | |
} // namespace WarningUtils | |
// Like Error, but we always report the C++ backtrace, instead of only | |
// reporting when TORCH_SHOW_CPP_STACKTRACES | |
class C10_API ErrorAlwaysShowCppStacktrace : public Error { | |
using Error::Error; | |
const char* what_without_backtrace() const noexcept override { | |
return what(); | |
} | |
}; | |
// Used in ATen for out-of-bound indices that can reasonably only be detected | |
// lazily inside a kernel (See: advanced indexing). These turn into | |
// IndexError when they cross to Python. | |
class C10_API IndexError : public Error { | |
using Error::Error; | |
}; | |
// Used in ATen for invalid values. These turn into | |
// ValueError when they cross to Python. | |
class C10_API ValueError : public Error { | |
using Error::Error; | |
}; | |
// Used in ATen for invalid types. These turn into | |
// TypeError when they cross to Python. | |
class C10_API TypeError : public Error { | |
using Error::Error; | |
}; | |
// Used in ATen for functionality that is not implemented. These turn into | |
// NotImplementedError when they cross to Python. | |
class C10_API NotImplementedError : public Error { | |
using Error::Error; | |
}; | |
// Used in ATen for non finite indices. These turn into | |
// ExitException when they cross to Python. | |
class C10_API EnforceFiniteError : public Error { | |
using Error::Error; | |
}; | |
// Used in Onnxifi backend lowering. These turn into | |
// ExitException when they cross to Python. | |
class C10_API OnnxfiBackendSystemError : public Error { | |
using Error::Error; | |
}; | |
// Used for numerical errors from the linalg module. These | |
// turn into LinAlgError when they cross into Python. | |
class C10_API LinAlgError : public Error { | |
using Error::Error; | |
}; | |
class C10_API OutOfMemoryError : public Error { | |
using Error::Error; | |
}; | |
// Base error type for all distributed errors. | |
// These turn into DistError when they cross into Python. | |
class C10_API DistError : public Error { | |
using Error::Error; | |
}; | |
// Used for collective communication library errors from the distributed module. | |
// These turn into DistBackendError when they cross into Python. | |
class C10_API DistBackendError : public DistError { | |
using DistError::DistError; | |
}; | |
// Used for errors originating from the store. | |
// These turn into DistStoreError when they cross into Python. | |
class C10_API DistStoreError : public DistError { | |
using DistError::DistError; | |
}; | |
// Used for errors originating from the TCP/IP stack and not from collective | |
// libraries. These turn into DistNetworkError when they cross into Python. | |
class C10_API DistNetworkError : public DistError { | |
using DistError::DistError; | |
}; | |
// A utility function to return an exception std::string by prepending its | |
// exception type before its what() content | |
C10_API std::string GetExceptionString(const std::exception& e); | |
} // namespace c10 | |
// Private helper macro for implementing TORCH_INTERNAL_ASSERT and TORCH_CHECK | |
// | |
// Note: In the debug build With MSVC, __LINE__ might be of long type (a.k.a | |
// int32_t), which is different from the definition of `SourceLocation` that | |
// requires unsigned int (a.k.a uint32_t) and may cause a compile error with the | |
// message: error C2397: conversion from 'long' to 'uint32_t' requires a | |
// narrowing conversion Here the static cast is used to pass the build. if this | |
// is used inside a lambda the __func__ macro expands to operator(), which isn't | |
// very useful, but hard to fix in a macro so suppressing the warning. | |
throw ::c10::err_type( \ | |
{__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, msg) | |
::c10::err_type({__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, msg) | |
// Private helper macro for workaround MSVC misexpansion of nested macro | |
// invocations involving __VA_ARGS__. See | |
// https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly | |
// On nvcc, C10_UNLIKELY thwarts missing return statement analysis. In cases | |
// where the unlikely expression may be a constant, use this macro to ensure | |
// return statement analysis keeps working (at the cost of not getting the | |
// likely/unlikely annotation on nvcc). | |
// https://github.com/pytorch/pytorch/issues/21418 | |
// | |
// Currently, this is only used in the error reporting macros below. If you | |
// want to use it more generally, move me to Macros.h | |
// | |
// TODO: Brian Vaughan observed that we might be able to get this to work on | |
// nvcc by writing some sort of C++ overload that distinguishes constexpr inputs | |
// from non-constexpr. Since there isn't any evidence that losing C10_UNLIKELY | |
// in nvcc is causing us perf problems, this is not yet implemented, but this | |
// might be an interesting piece of C++ code for an intrepid bootcamper to | |
// write. | |
// ---------------------------------------------------------------------------- | |
// Error reporting macros | |
// ---------------------------------------------------------------------------- | |
do { \ | |
e.add_context(::c10::str(__VA_ARGS__)); \ | |
throw; \ | |
} while (false) | |
// A utility macro to provide assert()-like functionality; that is, enforcement | |
// of internal invariants in code. It supports an arbitrary number of extra | |
// arguments (evaluated only on failure), which will be printed in the assert | |
// failure message using operator<< (this is useful to print some variables | |
// which may be useful for debugging.) | |
// | |
// Usage: | |
// TORCH_INTERNAL_ASSERT(should_be_true); | |
// TORCH_INTERNAL_ASSERT(x == 0, "x = ", x); | |
// | |
// Assuming no bugs in PyTorch, the conditions tested by this macro should | |
// always be true; e.g., it should be possible to disable all of these | |
// conditions without changing observable user behavior. If you would like to | |
// do error reporting for user input, please use TORCH_CHECK instead. | |
// | |
// NOTE: It is SAFE to use this macro in production code; on failure, this | |
// simply raises an exception, it does NOT unceremoniously quit the process | |
// (unlike assert()). | |
// | |
if (C10_UNLIKELY_OR_CONST(!(cond))) { \ | |
::c10::detail::torchCheckFail( \ | |
__func__, \ | |
__FILE__, \ | |
static_cast<uint32_t>(__LINE__), \ | |
} | |
// It would be nice if we could build a combined string literal out of | |
// the TORCH_INTERNAL_ASSERT prefix and a user-provided string literal | |
// as the first argument, but there doesn't seem to be any good way to | |
// do that while still supporting having a first argument that isn't a | |
// string literal. | |
if (C10_UNLIKELY_OR_CONST(!(cond))) { \ | |
::c10::detail::torchInternalAssertFail( \ | |
__func__, \ | |
__FILE__, \ | |
static_cast<uint32_t>(__LINE__), \ | |
" INTERNAL ASSERT FAILED at " C10_STRINGIZE(__FILE__) ":" C10_STRINGIZE( \ | |
__LINE__) ", please report a bug to PyTorch. ", \ | |
c10::str(__VA_ARGS__)); \ | |
} | |
// A utility macro to make it easier to test for error conditions from user | |
// input. Like TORCH_INTERNAL_ASSERT, it supports an arbitrary number of extra | |
// arguments (evaluated only on failure), which will be printed in the error | |
// message using operator<< (e.g., you can pass any object which has | |
// operator<< defined. Most objects in PyTorch have these definitions!) | |
// | |
// Usage: | |
// TORCH_CHECK(should_be_true); // A default error message will be provided | |
// // in this case; but we recommend writing an | |
// // explicit error message, as it is more | |
// // user friendly. | |
// TORCH_CHECK(x == 0, "Expected x to be 0, but got ", x); | |
// | |
// On failure, this macro will raise an exception. If this exception propagates | |
// to Python, it will convert into a Python RuntimeError. | |
// | |
// NOTE: It is SAFE to use this macro in production code; on failure, this | |
// simply raises an exception, it does NOT unceremoniously quit the process | |
// (unlike CHECK() from glog.) | |
// | |
TORCH_CHECK_WITH_MSG(error_t, cond, "", __VA_ARGS__) | |
( | |
if (C10_UNLIKELY_OR_CONST(!(cond))) { \ | |
C10_THROW_ERROR(Error, TORCH_CHECK_MSG(cond, type, __VA_ARGS__)); \ | |
} | |
namespace c10::detail { | |
template <typename... Args> | |
decltype(auto) torchCheckMsgImpl(const char* /*msg*/, const Args&... args) { | |
return ::c10::str(args...); | |
} | |
inline C10_API const char* torchCheckMsgImpl(const char* msg) { | |
return msg; | |
} | |
// If there is just 1 user-provided C-string argument, use it. | |
inline C10_API const char* torchCheckMsgImpl( | |
const char* /*msg*/, | |
const char* args) { | |
return args; | |
} | |
} // namespace c10::detail | |
(::c10::detail::torchCheckMsgImpl( \ | |
"Expected " | |
" to be true, but got false. " \ | |
"(Could this error message be improved? If so, " \ | |
"please report an enhancement request to PyTorch.)", \ | |
##__VA_ARGS__)) | |
if (C10_UNLIKELY_OR_CONST(!(cond))) { \ | |
C10_THROW_ERROR(error_t, TORCH_CHECK_MSG(cond, type, __VA_ARGS__)); \ | |
} | |
namespace c10::detail { | |
[[noreturn]] C10_API void torchCheckFail( | |
const char* func, | |
const char* file, | |
uint32_t line, | |
const std::string& msg); | |
[[noreturn]] C10_API void torchCheckFail( | |
const char* func, | |
const char* file, | |
uint32_t line, | |
const char* msg); | |
// The c10::str() call that creates userMsg can have 1 of 3 return | |
// types depending on the number and types of arguments passed to | |
// TORCH_INTERNAL_ASSERT. 0 arguments will get a | |
// CompileTimeEmptyString, 1 const char * will be passed straight | |
// through, and anything else will get converted to std::string. | |
[[noreturn]] C10_API void torchInternalAssertFail( | |
const char* func, | |
const char* file, | |
uint32_t line, | |
const char* condMsg, | |
const char* userMsg); | |
[[noreturn]] inline C10_API void torchInternalAssertFail( | |
const char* func, | |
const char* file, | |
uint32_t line, | |
const char* condMsg, | |
::c10::detail::CompileTimeEmptyString /*userMsg*/) { | |
torchCheckFail(func, file, line, condMsg); | |
} | |
[[noreturn]] C10_API void torchInternalAssertFail( | |
const char* func, | |
const char* file, | |
uint32_t line, | |
const char* condMsg, | |
const std::string& userMsg); | |
} // namespace c10::detail | |
if (C10_UNLIKELY_OR_CONST(!(cond))) { \ | |
::c10::detail::torchCheckFail( \ | |
__func__, \ | |
__FILE__, \ | |
static_cast<uint32_t>(__LINE__), \ | |
TORCH_CHECK_MSG(cond, "", __VA_ARGS__)); \ | |
} | |
if (C10_UNLIKELY_OR_CONST(!(cond))) { \ | |
::c10::detail::torchCheckFail( \ | |
__func__, \ | |
__FILE__, \ | |
static_cast<uint32_t>(__LINE__), \ | |
TORCH_CHECK_MSG(cond, "", ##__VA_ARGS__)); \ | |
} | |
// An utility macro that does what `TORCH_CHECK` does if compiled in the host | |
// code, otherwise does nothing. Supposed to be used in the code shared between | |
// host and device code as an alternative for `TORCH_CHECK`. | |
// Debug only version of TORCH_INTERNAL_ASSERT. This macro only checks in debug | |
// build, and does nothing in release build. It is appropriate to use | |
// in situations where you want to add an assert to a hotpath, but it is | |
// too expensive to run this assert on production builds. | |
// Optimized version - generates no code. | |
while (false) \ | |
C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(__VA_ARGS__)) | |
C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(__VA_ARGS__)) | |
// TODO: We're going to get a lot of similar looking string literals | |
// this way; check if this actually affects binary size. | |
// Like TORCH_CHECK, but raises LinAlgError instead of Error. | |
TORCH_CHECK_WITH_MSG(LinAlgError, cond, "LINALG", __VA_ARGS__) | |
// Like TORCH_CHECK, but raises IndexErrors instead of Errors. | |
TORCH_CHECK_WITH_MSG(IndexError, cond, "INDEX", __VA_ARGS__) | |
// Like TORCH_CHECK, but raises ValueErrors instead of Errors. | |
TORCH_CHECK_WITH_MSG(ValueError, cond, "VALUE", __VA_ARGS__) | |
// Like TORCH_CHECK, but raises TypeErrors instead of Errors. | |
TORCH_CHECK_WITH_MSG(TypeError, cond, "TYPE", __VA_ARGS__) | |
// Like TORCH_CHECK, but raises NotImplementedErrors instead of Errors. | |
TORCH_CHECK_WITH_MSG(NotImplementedError, cond, "TYPE", __VA_ARGS__) | |
TORCH_CHECK_WITH_MSG( \ | |
ErrorAlwaysShowCppStacktrace, cond, "TYPE", ##__VA_ARGS__) | |
::c10::detail::CompileTimeEmptyString {} | |
// Report a warning to the user. Accepts an arbitrary number of extra | |
// arguments which are concatenated into the warning message using operator<< | |
// | |
::c10::warn(::c10::Warning( \ | |
warning_t(), \ | |
{__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, \ | |
WARNING_MESSAGE_STRING(__VA_ARGS__), \ | |
false)); | |
_TORCH_WARN_WITH(::c10::DeprecationWarning, __VA_ARGS__); | |
// Report a warning to the user only once. Accepts an arbitrary number of extra | |
// arguments which are concatenated into the warning message using operator<< | |
// | |
C10_UNUSED static const auto C10_ANONYMOUS_VARIABLE(torch_warn_once_) = \ | |
[&] { \ | |
TORCH_WARN(__VA_ARGS__); \ | |
return true; \ | |
}() | |
if (::c10::WarningUtils::get_warnAlways()) { \ | |
TORCH_WARN(__VA_ARGS__); \ | |
} else { \ | |
_TORCH_WARN_ONCE(__VA_ARGS__); \ | |
} | |
// Report an error with a specific argument | |
// NOTE: using the argument name in TORCH_CHECK's message is preferred | |
TORCH_CHECK(cond, "invalid argument ", argN, ": ", __VA_ARGS__) | |
// ---------------------------------------------------------------------------- | |
// Deprecated macros | |
// ---------------------------------------------------------------------------- | |
namespace c10::detail { | |
/* | |
// Deprecation disabled until we fix sites in our codebase | |
C10_DEPRECATED_MESSAGE("AT_ERROR(msg) is deprecated, use TORCH_CHECK(false, msg) | |
instead.") | |
*/ | |
inline void deprecated_AT_ERROR() {} | |
/* | |
// Deprecation disabled until we fix sites in our codebase | |
C10_DEPRECATED_MESSAGE("AT_ASSERT is deprecated, if you mean to indicate an | |
internal invariant failure, use " \ | |
"TORCH_INTERNAL_ASSERT instead; if you mean to do user | |
error checking, use " \ "TORCH_CHECK. See | |
https://github.com/pytorch/pytorch/issues/20287 for more details.") | |
*/ | |
inline void deprecated_AT_ASSERT() {} | |
/* | |
// Deprecation disabled until we fix sites in our codebase | |
C10_DEPRECATED_MESSAGE("AT_ASSERTM is deprecated, if you mean to indicate an | |
internal invariant failure, use " \ | |
"TORCH_INTERNAL_ASSERT instead; if you mean to do user | |
error checking, use " \ "TORCH_CHECK. See | |
https://github.com/pytorch/pytorch/issues/20287 for more details.") | |
*/ | |
inline void deprecated_AT_ASSERTM() {} | |
} // namespace c10::detail | |
// Deprecated alias; this alias was deprecated because people kept mistakenly | |
// using it for user error checking. Use TORCH_INTERNAL_ASSERT or TORCH_CHECK | |
// instead. See https://github.com/pytorch/pytorch/issues/20287 for more | |
// details. | |
do { \ | |
::c10::detail::deprecated_AT_ASSERT(); \ | |
C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(__VA_ARGS__)); \ | |
} while (false) | |
// Deprecated alias, like AT_ASSERT. The new TORCH_INTERNAL_ASSERT macro | |
// supports both 0-ary and variadic calls, so having a separate | |
// message-accepting macro is not necessary. | |
// | |
// NB: we MUST include cond explicitly here, as MSVC will miscompile the macro | |
// expansion, shunting all of __VA_ARGS__ to cond. An alternate workaround | |
// can be seen at | |
// https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly | |
do { \ | |
::c10::detail::deprecated_AT_ASSERTM(); \ | |
C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(cond, __VA_ARGS__)); \ | |
} while (false) | |
// Deprecated alias; this alias was deprecated because it represents extra API | |
// surface that makes it hard for people to understand what macro to use. | |
// Use TORCH_CHECK(false, ...) or TORCH_INTERNAL_ASSERT(false, ...) to | |
// unconditionally fail at a line of code. | |
do { \ | |
::c10::detail::deprecated_AT_ERROR(); \ | |
C10_EXPAND_MSVC_WORKAROUND(TORCH_CHECK(false, ::c10::str(__VA_ARGS__))); \ | |
} while (false) | |