Files
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

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)
}