#ifndef COMMON_VERBOSE_HPP
#define COMMON_VERBOSE_HPP
#include <cinttypes>
#include <cstdio>
#include <mutex>
#include <stdio.h>
#include "c_types_map.hpp"
#include "oneapi/dnnl/dnnl_debug.h"
#include "utils.hpp"
#include "z_magic.hpp"
#include "profiler.hpp"
#include "verbose_msg.hpp"
#ifdef DNNL_EXPERIMENTAL_LOGGING
#include "common/logging.hpp"
#endif
namespace dnnl {
namespace impl {
namespace utility {
template <typename T, size_t S>
inline constexpr size_t get_file_name_offset(
const T (&str)[S], size_t i = S - 1) {
return (i + 3 < S) && str[i] == 's' && str[i + 1] == 'r'
&& str[i + 2] == 'c'
&& (str[i + 3] == '/' || str[i + 3] == '\\')
? i
: (i > 3 ? get_file_name_offset(str, i - 1) : 0);
}
template <typename T>
inline constexpr size_t get_file_name_offset(T (&str)[1]) {
return 0;
}
template <typename T, T v>
struct const_expr_value_t {
static constexpr const T value = v;
};
}
#if defined(__GNUC__) || defined(__clang__)
static inline int format_type_checker(const char *, ...)
__attribute__((format(printf, 1, 2)));
#endif
static inline int format_type_checker(const char *, ...) {
return 0;
}
#define UTILITY_CONST_EXPR_VALUE(exp) \
dnnl::impl::utility::const_expr_value_t<decltype(exp), exp>::value
#define __FILENAME__ \
(&__FILE__[dnnl::impl::utility::get_file_name_offset(__FILE__)])
#define VFORMAT(stamp, flagkind, apitype, logtype, logsubtype, msg, ...) \
do { \
std::string stamp_; \
if (dnnl::impl::get_verbose_timestamp()) \
stamp_ = std::to_string(stamp) + ","; \
dnnl::impl::format_type_checker( \
"%s" CONCAT2(VERBOSE_, apitype) "," CONCAT2( \
VERBOSE_, logtype) "%s," msg "\n", \
stamp_.c_str(), logsubtype, ##__VA_ARGS__); \
dnnl::impl::verbose_printf(flagkind, \
"%s" CONCAT2(VERBOSE_, apitype) "," CONCAT2( \
VERBOSE_, logtype) "%s," msg "\n", \
stamp_.c_str(), logsubtype, ##__VA_ARGS__); \
} while (0)
#define VINFO(apitype, logtype, logsubtype, component, msg, ...) \
do { \
if (dnnl::impl::get_verbose( \
dnnl::impl::verbose_t::logtype##_##logsubtype)) \
VFORMAT(dnnl::impl::get_msec(), \
dnnl::impl::verbose_t::logtype##_##logsubtype, apitype, \
logtype, VERBOSE_##logsubtype, \
#component "," msg ",%s:%d", ##__VA_ARGS__, __FILENAME__, \
__LINE__); \
} while (0)
#define VCONDCHECK( \
apitype, logtype, logsubtype, component, condition, status, msg, ...) \
do { \
if (!(condition)) { \
VINFO(apitype, logtype, logsubtype, component, msg, \
##__VA_ARGS__); \
return status; \
} \
} while (0)
#define VCHECK(apitype, logtype, logsubtype, component, f, msg, ...) \
do { \
status_t _status_ = (f); \
VCONDCHECK(apitype, logtype, logsubtype, component, \
_status_ == dnnl::impl::status::success, _status_, msg, \
##__VA_ARGS__); \
} while (0)
#define VERROR(apitype, component, msg, ...) \
do { \
if (dnnl::impl::get_verbose(dnnl::impl::verbose_t::error)) { \
VFORMAT(dnnl::impl::get_msec(), dnnl::impl::verbose_t::error, \
apitype, error, "", #component "," msg ",%s:%d", \
##__VA_ARGS__, __FILENAME__, __LINE__); \
} \
} while (0)
#define VWARN(apitype, component, msg, ...) \
do { \
if (dnnl::impl::get_verbose(dnnl::impl::verbose_t::warn)) { \
VFORMAT(dnnl::impl::get_msec(), dnnl::impl::verbose_t::warn, \
apitype, warn, "", #component "," msg ",%s:%d", \
##__VA_ARGS__, __FILENAME__, __LINE__); \
} \
} while (0)
#define VDEBUGINFO(level, apitype, component, msg, ...) \
do { \
if (dnnl::impl::get_verbose_dev_mode(dnnl::impl::verbose_t::debuginfo) \
>= (level)) { \
VFORMAT(dnnl::impl::get_msec(), dnnl::impl::verbose_t::debuginfo, \
apitype, debuginfo, "", #component "," msg ",%s:%d", \
##__VA_ARGS__, __FILENAME__, __LINE__); \
} \
} while (0)
#define VPROF(stamp, apitype, logtype, logsubtype, info, duration) \
{ \
auto flag = dnnl::impl::verbose_t::exec_profile; \
if (strcmp(#logtype, "create") == 0 \
|| strcmp(#logtype, "create_nested") == 0) \
flag = dnnl::impl::verbose_t::create_profile; \
VFORMAT(stamp, flag, apitype, logtype, logsubtype, "%s,%g", info, \
duration); \
}
struct verbose_t {
enum flag_kind : uint32_t {
none = 0,
error = 1 << 2,
create_check = 1 << 3,
create_dispatch = 1 << 4,
create_profile = 1 << 5,
exec_check = 1 << 6,
exec_profile = 1 << 7,
profile_externals = 1 << 8,
warn = 1 << 9,
debuginfo = 1 << 24,
level1 = error | exec_profile | warn,
level2 = error | exec_profile | warn | create_profile,
all = (uint32_t)-1,
};
static uint32_t make_debuginfo(uint32_t level) { return level << 24; }
static uint32_t get_debuginfo(uint32_t flag) { return flag >> 24; }
};
struct component_t {
enum flag_kind : uint32_t {
none = 0,
primitive = 1 << 0,
reorder = 1 << 1,
shuffle = 1 << 2,
concat = 1 << 3,
sum = 1 << 4,
convolution = 1 << 5,
deconvolution = 1 << 6,
eltwise = 1 << 7,
lrn = 1 << 8,
batch_normalization = 1 << 9,
inner_product = 1 << 10,
rnn = 1 << 11,
gemm = 1 << 12,
binary = 1 << 13,
matmul = 1 << 14,
resampling = 1 << 15,
pooling = 1 << 16,
reduction = 1 << 17,
prelu = 1 << 18,
softmax = 1 << 19,
layer_normalization = 1 << 20,
group_normalization = 1 << 21,
graph = 1 << 22,
gemm_api = 1 << 23,
ukernel = 1 << 24,
all = (uint32_t)-1,
};
};
struct filter_status_t {
enum flags : uint32_t {
none = 0,
valid,
invalid,
};
flags status = flags::none;
std::string components;
std::string err_msg;
};
inline component_t::flag_kind prim_kind2_comp_kind(
const primitive_kind_t prim_kind) {
if (prim_kind >= primitive_kind::internal_only_start)
return component_t::all;
return static_cast<component_t::flag_kind>(1 << prim_kind | 1 << 0);
}
uint32_t get_verbose(verbose_t::flag_kind kind = verbose_t::none,
component_t::flag_kind filter_kind = component_t::all) noexcept;
static inline uint32_t get_verbose_dev_mode(
verbose_t::flag_kind kind = verbose_t::none) {
return is_dev_mode() ? get_verbose(kind) : 0;
}
bool get_verbose_timestamp();
#ifdef DNNL_EXPERIMENTAL_LOGGING
inline const std::map<dnnl::impl::verbose_t::flag_kind,
log_manager_t::log_level_t> &
get_verbose_to_log_level_map() {
static const std::map<dnnl::impl::verbose_t::flag_kind,
log_manager_t::log_level_t>
verbose_to_log_map {
{verbose_t::all, log_manager_t::trace},
{verbose_t::debuginfo, log_manager_t::debug},
{verbose_t::level1, log_manager_t::info},
{verbose_t::level2, log_manager_t::info},
{verbose_t::create_dispatch, log_manager_t::info},
{verbose_t::create_check, log_manager_t::info},
{verbose_t::create_profile, log_manager_t::info},
{verbose_t::profile_externals, log_manager_t::info},
{verbose_t::exec_profile, log_manager_t::info},
{verbose_t::exec_check, log_manager_t::error},
{verbose_t::error, log_manager_t::critical},
{verbose_t::warn, log_manager_t::warn},
{verbose_t::none, log_manager_t::off},
};
return verbose_to_log_map;
}
inline log_manager_t::log_level_t align_verbose_mode_to_log_level(
verbose_t::flag_kind kind) {
const auto &map = get_verbose_to_log_level_map();
auto it = map.find(kind);
if (it != map.end()) {
return it->second;
} else {
return log_manager_t::off;
}
}
#endif
void verbose_printf_impl(const char *fmt_str, verbose_t::flag_kind kind);
template <typename... str_args>
inline std::string format_verbose_string(
const char *fmt_str, str_args... args) {
const int size = snprintf(nullptr, 0, fmt_str, args...) + 1;
if (size == 0) {
return "info,error encountered while formatting verbose message\n";
}
std::string msg(size, '\0');
snprintf(&msg[0], size, fmt_str, args...);
return msg;
}
inline void verbose_printf(const char *fmt_str) {
verbose_printf_impl(fmt_str, verbose_t::create_check);
}
inline void verbose_printf(verbose_t::flag_kind kind, const char *fmt_str) {
verbose_printf_impl(fmt_str, kind);
}
template <typename... str_args>
inline void verbose_printf(const char *fmt_str, str_args... args) {
std::string msg = format_verbose_string(fmt_str, args...);
verbose_printf_impl(msg.c_str(), verbose_t::create_check);
}
template <typename... str_args>
inline void verbose_printf(
verbose_t::flag_kind kind, const char *fmt_str, str_args... args) {
std::string msg = format_verbose_string(fmt_str, args...);
verbose_printf_impl(msg.c_str(), kind);
}
struct primitive_desc_t;
struct pd_info_t {
pd_info_t() = default;
pd_info_t(const pd_info_t &rhs)
: str_(rhs.str_), is_initialized_(rhs.is_initialized_) {}
pd_info_t &operator=(const pd_info_t &rhs) {
is_initialized_ = rhs.is_initialized_;
str_ = rhs.str_;
return *this;
}
~pd_info_t() = default;
const char *c_str() const { return str_.c_str(); }
bool is_initialized() const { return is_initialized_; }
void init(engine_t *engine, const primitive_desc_t *pd);
private:
std::string str_;
#if defined(DISABLE_VERBOSE)
bool is_initialized_ = true; #else
bool is_initialized_ = false;
#endif
std::once_flag initialization_flag_;
};
enum class dims_type_t {
undef,
dims,
strides,
};
std::string md2fmt_str(
const char *name, const memory_desc_t *md, format_kind_t user_format);
std::string md2dim_str(
const memory_desc_t *md, dims_type_t dims_type = dims_type_t::dims);
std::string arg2str(int arg);
std::string rt_dims2fmt_str(primitive_kind_t prim_kind,
const memory_desc_t *src_md, const memory_desc_t *wei_md,
const memory_desc_t *dst_md);
std::string rt_mds2str(primitive_kind_t prim_kind, const memory_desc_t *src_md,
const memory_desc_t *wei_md, const memory_desc_t *bia_md,
const memory_desc_t *dst_md);
std::string attr2str(const primitive_attr_t *attr);
std::string md2fmt_tag_str(const memory_desc_t *md);
} }
#endif