CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
317 lines
11 KiB
C++
317 lines
11 KiB
C++
// Copyright © Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
/**
|
|
* @file Error.hpp
|
|
* @brief Error handling types and macros for the hipDNN Frontend API
|
|
*
|
|
* This file defines the error handling infrastructure used throughout the hipDNN
|
|
* frontend. It includes error codes, the Error struct for detailed error information,
|
|
* and helper macros for error checking and propagation.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <ostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
/**
|
|
* @brief Check an Error return value and propagate if an error occurred
|
|
* @param x Expression returning an Error object
|
|
*
|
|
* This macro evaluates the expression and returns immediately if the result
|
|
* indicates an error (is_bad() returns true).
|
|
*/
|
|
#define HIPDNN_CHECK_ERROR(x) \
|
|
do \
|
|
{ \
|
|
const auto err = x; \
|
|
if(err.is_bad()) \
|
|
{ \
|
|
return err; \
|
|
} \
|
|
} while(0)
|
|
|
|
namespace hipdnn_frontend
|
|
{
|
|
/**
|
|
* @enum ErrorCode
|
|
* @brief Error codes returned by hipDNN Frontend operations
|
|
*
|
|
* Portions derived from NVIDIA cuDNN frontend, used under the MIT license.
|
|
*/
|
|
enum class ErrorCode
|
|
{
|
|
OK, ///< Operation completed successfully
|
|
INVALID_VALUE, ///< An invalid value was provided
|
|
HIPDNN_BACKEND_ERROR, ///< An error occurred in the hipDNN backend
|
|
ATTRIBUTE_NOT_SET, ///< A required attribute was not set
|
|
/**
|
|
* @brief No engine accepted this graph
|
|
*
|
|
* No engine has an applicable solution on the current device, likely
|
|
* because the requested dtype/shape/operation pattern is not supported by
|
|
* any engine. Distinct from validation errors -- the graph is well-formed,
|
|
* just not runnable by the available engines.
|
|
*/
|
|
GRAPH_NOT_SUPPORTED, ///< No engine accepted this graph (graph well-formed but unrunnable on available engines)
|
|
SHAPE_DEDUCTION_FAILED, ///< Tensor shape/stride deduction failed
|
|
INVALID_TENSOR_NAME, ///< A referenced tensor name is invalid
|
|
INVALID_VARIANT_PACK, ///< The variant pack provided to execute() is invalid
|
|
GRAPH_EXECUTION_PLAN_CREATION_FAILED, ///< Creating an execution plan for the graph failed
|
|
GRAPH_EXECUTION_FAILED, ///< Executing the graph failed
|
|
HEURISTIC_QUERY_FAILED, ///< Querying heuristics for the graph failed
|
|
UNSUPPORTED_GRAPH_FORMAT, ///< The graph format is unsupported
|
|
CUDA_API_FAILED, ///< A CUDA runtime API call failed (CUDA-specific; not produced by hipDNN)
|
|
CUDNN_BACKEND_API_FAILED, ///< A cuDNN backend API call failed (CUDA-specific; not produced by hipDNN)
|
|
INVALID_CUDA_DEVICE, ///< The CUDA device is invalid (CUDA-specific; not produced by hipDNN)
|
|
HANDLE_ERROR, ///< A handle-related error occurred
|
|
NVRTC_COMPILATION_FAILED ///< Runtime kernel compilation via NVRTC failed (CUDA-specific; not produced by hipDNN)
|
|
};
|
|
|
|
// NOLINTNEXTLINE(readability-identifier-naming)
|
|
inline std::string to_string(ErrorCode code)
|
|
{
|
|
switch(code)
|
|
{
|
|
case ErrorCode::OK:
|
|
return "OK";
|
|
case ErrorCode::INVALID_VALUE:
|
|
return "INVALID_VALUE";
|
|
case ErrorCode::HIPDNN_BACKEND_ERROR:
|
|
return "HIPDNN_BACKEND_ERROR";
|
|
case ErrorCode::ATTRIBUTE_NOT_SET:
|
|
return "ATTRIBUTE_NOT_SET";
|
|
case ErrorCode::GRAPH_NOT_SUPPORTED:
|
|
return "GRAPH_NOT_SUPPORTED";
|
|
case ErrorCode::SHAPE_DEDUCTION_FAILED:
|
|
return "SHAPE_DEDUCTION_FAILED";
|
|
case ErrorCode::INVALID_TENSOR_NAME:
|
|
return "INVALID_TENSOR_NAME";
|
|
case ErrorCode::INVALID_VARIANT_PACK:
|
|
return "INVALID_VARIANT_PACK";
|
|
case ErrorCode::GRAPH_EXECUTION_PLAN_CREATION_FAILED:
|
|
return "GRAPH_EXECUTION_PLAN_CREATION_FAILED";
|
|
case ErrorCode::GRAPH_EXECUTION_FAILED:
|
|
return "GRAPH_EXECUTION_FAILED";
|
|
case ErrorCode::HEURISTIC_QUERY_FAILED:
|
|
return "HEURISTIC_QUERY_FAILED";
|
|
case ErrorCode::UNSUPPORTED_GRAPH_FORMAT:
|
|
return "UNSUPPORTED_GRAPH_FORMAT";
|
|
case ErrorCode::CUDA_API_FAILED:
|
|
return "CUDA_API_FAILED";
|
|
case ErrorCode::CUDNN_BACKEND_API_FAILED:
|
|
return "CUDNN_BACKEND_API_FAILED";
|
|
case ErrorCode::INVALID_CUDA_DEVICE:
|
|
return "INVALID_CUDA_DEVICE";
|
|
case ErrorCode::HANDLE_ERROR:
|
|
return "HANDLE_ERROR";
|
|
case ErrorCode::NVRTC_COMPILATION_FAILED:
|
|
return "NVRTC_COMPILATION_FAILED";
|
|
default:
|
|
return "UNKNOWN_ERROR";
|
|
}
|
|
}
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const ErrorCode& error)
|
|
{
|
|
return os << to_string(error);
|
|
}
|
|
|
|
typedef ErrorCode error_code_t; ///< @brief Type alias for ErrorCode
|
|
|
|
/**
|
|
* @struct Error
|
|
* @brief Represents an error with a code and descriptive message
|
|
*
|
|
* The Error struct is the primary mechanism for reporting errors in hipDNN Frontend
|
|
* operations. It combines an ErrorCode with a human-readable message describing
|
|
* what went wrong.
|
|
*
|
|
* @code{.cpp}
|
|
* Error result = graph.build(handle);
|
|
* if(result.is_bad())
|
|
* {
|
|
* std::cerr << "Build failed: " << result.get_message() << std::endl;
|
|
* }
|
|
* @endcode
|
|
*/
|
|
struct Error
|
|
{
|
|
ErrorCode code; ///< The error code
|
|
std::string err_msg; ///< Detailed error message // NOLINT(readability-identifier-naming)
|
|
|
|
/**
|
|
* @brief Default constructor, creates a success result
|
|
*/
|
|
Error()
|
|
: code(ErrorCode::OK)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Construct an Error with a specific code and message
|
|
* @param errorCode The error code
|
|
* @param message Descriptive message about the error
|
|
*/
|
|
Error(ErrorCode errorCode, std::string message)
|
|
: code(errorCode)
|
|
, err_msg(std::move(message))
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Get the error message
|
|
* @return The error message string
|
|
*/
|
|
std::string get_message() const // NOLINT(readability-identifier-naming)
|
|
{
|
|
return err_msg;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the error code
|
|
* @return The ErrorCode value
|
|
*/
|
|
ErrorCode get_code() const // NOLINT(readability-identifier-naming)
|
|
{
|
|
return code;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the operation succeeded
|
|
* @return true if code == ErrorCode::OK, false otherwise
|
|
*/
|
|
bool is_good() const // NOLINT(readability-identifier-naming)
|
|
{
|
|
return code == ErrorCode::OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the operation failed
|
|
* @return true if code != ErrorCode::OK, false otherwise
|
|
*/
|
|
bool is_bad() const // NOLINT(readability-identifier-naming)
|
|
{
|
|
return code != ErrorCode::OK;
|
|
}
|
|
|
|
/// @brief Compare error code with an ErrorCode value
|
|
bool operator==(ErrorCode otherCode) const
|
|
{
|
|
return code == otherCode;
|
|
}
|
|
/// @brief Compare error code with an ErrorCode value (inequality)
|
|
bool operator!=(ErrorCode otherCode) const
|
|
{
|
|
return code != otherCode;
|
|
}
|
|
/// @brief Compare two Error objects by their error codes
|
|
bool operator==(const Error& other) const
|
|
{
|
|
return code == other.code;
|
|
}
|
|
/// @brief Compare two Error objects by their error codes (inequality)
|
|
bool operator!=(const Error& other) const
|
|
{
|
|
return code != other.code;
|
|
}
|
|
};
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const Error& error)
|
|
{
|
|
return os << "{" << error.code << ", " << error.get_message() << "}";
|
|
}
|
|
|
|
typedef Error error_object; ///< @brief Type alias for Error (compatibility)
|
|
typedef Error error_t; ///< @brief Type alias for Error
|
|
|
|
#define HIPDNN_RETURN_IF_NE(x, y, error_status, message) \
|
|
do \
|
|
{ \
|
|
if((x) != (y)) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_EQ(x, y, error_status, message) \
|
|
do \
|
|
{ \
|
|
if((x) == (y)) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_TRUE(x, error_status, message) \
|
|
do \
|
|
{ \
|
|
if(x) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_FALSE(x, error_status, message) \
|
|
do \
|
|
{ \
|
|
if(!(x)) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_NULL(x, error_status, message) \
|
|
do \
|
|
{ \
|
|
if((x) == nullptr) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_LT(x, y, error_status, message) \
|
|
do \
|
|
{ \
|
|
if((x) < (y)) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_GE(x, y, error_status, message) \
|
|
do \
|
|
{ \
|
|
if((x) >= (y)) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define HIPDNN_RETURN_IF_LE(x, y, error_status, message) \
|
|
do \
|
|
{ \
|
|
if((x) <= (y)) \
|
|
{ \
|
|
return {error_status, message}; \
|
|
} \
|
|
} while(0)
|
|
|
|
/// Evaluate an expression that returns Error and early-return
|
|
/// \c {err, {}} when the error is bad. Works with any function whose
|
|
/// return type is \c std::pair<Error, T> because \c {} value-initialises
|
|
/// the second element (std::nullopt for optionals, default-constructed
|
|
/// pairs, etc.).
|
|
#define HIPDNN_FE_TRY(expr) \
|
|
do \
|
|
{ \
|
|
auto _fe_try_err = (expr); \
|
|
if(_fe_try_err.is_bad()) \
|
|
{ \
|
|
return {_fe_try_err, {}}; \
|
|
} \
|
|
} while(0)
|
|
}
|