#include <atomic>
#include <regex>
#include <sstream>
#include <type_traits>
#include <stdlib.h>
#ifndef _WIN32
#include <sys/time.h>
#else
#include <windows.h>
#endif
#include "oneapi/dnnl/dnnl.h"
#include "oneapi/dnnl/dnnl_debug.h"
#include "oneapi/dnnl/dnnl_version.h"
#include "oneapi/dnnl/dnnl_version_hash.h"
#include "c_types_map.hpp"
#include "verbose.hpp"
#include "batch_normalization_pd.hpp"
#include "binary_pd.hpp"
#include "concat_pd.hpp"
#include "convolution_pd.hpp"
#include "deconvolution_pd.hpp"
#include "eltwise_pd.hpp"
#include "gated_mlp_pd.hpp"
#include "gemm_pd.hpp"
#include "group_normalization_pd.hpp"
#include "inner_product_pd.hpp"
#include "layer_normalization_pd.hpp"
#include "lrn_pd.hpp"
#include "matmul_pd.hpp"
#include "pooling_pd.hpp"
#include "prelu_pd.hpp"
#include "reduction_pd.hpp"
#include "reorder_pd.hpp"
#include "resampling_pd.hpp"
#include "rnn_pd.hpp"
#include "sdpa_pd.hpp"
#include "shuffle_pd.hpp"
#include "softmax_pd.hpp"
#include "sum_pd.hpp"
#if DNNL_CPU_RUNTIME != DNNL_RUNTIME_NONE
#include "common/dnnl_thread.hpp"
#include "cpu/platform.hpp"
#endif
#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_OCL
#include "xpu/ocl/verbose.hpp"
#endif
#ifdef DNNL_WITH_SYCL
#include "xpu/sycl/verbose.hpp"
#endif
#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_ZE
#include "xpu/ze/verbose.hpp"
#endif
#ifdef DNNL_EXPERIMENTAL
#include "common/experimental.hpp"
#endif
namespace dnnl {
namespace impl {
static constexpr char verbose_version[] = "v1";
static setting_t<uint32_t> verbose {0};
filter_status_t &filter_status() {
static filter_status_t filter_status;
return filter_status;
}
void print_header() noexcept {
static std::atomic_flag version_printed = ATOMIC_FLAG_INIT;
if (!version_printed.test_and_set()) {
verbose_printf("info,oneDNN v%d.%d.%d (commit %s)\n",
dnnl_version()->major, dnnl_version()->minor,
dnnl_version()->patch, dnnl_version()->hash);
#if DNNL_CPU_RUNTIME != DNNL_RUNTIME_NONE
verbose_printf("info,cpu,runtime:%s,nthr:%d\n",
dnnl_runtime2str(dnnl_version()->cpu_runtime),
dnnl_get_max_threads());
verbose_printf("info,cpu,isa:%s\n", cpu::platform::get_isa_info());
#endif
verbose_printf("info,gpu,runtime:%s\n",
dnnl_runtime2str(dnnl_version()->gpu_runtime));
try {
#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_OCL
xpu::ocl::print_verbose_header();
#endif
#ifdef DNNL_WITH_SYCL
xpu::sycl::print_verbose_header();
#endif
#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_ZE
xpu::ze::print_verbose_header();
#endif
#ifdef ONEDNN_BUILD_GRAPH
graph::utils::print_verbose_header();
#endif
} catch (...) {
verbose_printf("info,exception while printing verbose header\n");
}
#ifdef DNNL_EXPERIMENTAL
verbose_printf("info,experimental features are enabled\n");
verbose_printf("info,use batch_normalization stats one pass is %s\n",
experimental::use_bnorm_stats_one_pass() ? "enabled"
: "disabled");
verbose_printf("info,GPU convolution v2 is %s\n",
experimental::use_gpu_conv_v2() ? "enabled" : "disabled");
#endif
#ifdef DNNL_EXPERIMENTAL_LOGGING
const log_manager_t &log_manager = log_manager_t::get_log_manager();
if (log_manager.is_logger_enabled())
verbose_printf(
"info,experimental functionality for logging is enabled\n");
#endif
#ifdef DNNL_EXPERIMENTAL_SYCL_KERNEL_COMPILER
verbose_printf("info,experimental SYCL kernel compiler is enabled\n");
#endif
verbose_printf(
"primitive,info,template:%soperation,engine,primitive,"
"implementation,prop_kind,memory_descriptors,attributes,"
"auxiliary,problem_desc,exec_time\n",
get_verbose_timestamp() ? "timestamp," : "");
#ifdef ONEDNN_BUILD_GRAPH
verbose_printf(
"graph,info,template:%soperation,engine,partition_id,"
"partition_kind,op_names,data_formats,logical_tensors,fpmath_"
"mode,implementation,backend,exec_time\n",
get_verbose_timestamp() ? "timestamp," : "");
#endif
if (filter_status().status == filter_status_t::flags::valid)
verbose_printf(
"common,info,filter format is enabled, hit components: "
"%s\n",
filter_status().components.c_str());
else if (filter_status().status == filter_status_t::flags::invalid)
verbose_printf(
"common,error,filter format is ill-formed and is not "
"applied, error: %s\n",
filter_status().err_msg.c_str());
}
}
uint32_t get_verbose(verbose_t::flag_kind verbosity_kind,
component_t::flag_kind filter_kind) noexcept {
#if defined(DISABLE_VERBOSE)
return verbose_t::none;
#endif
static int flags = component_t::all;
if (!verbose.initialized()) {
static std::string user_opt = getenv_string_user("VERBOSE");
auto update_kind = [&](const std::string &s, int &k) {
if (s == "0" || s == "none") k = verbose_t::none;
if (s == "1") k |= verbose_t::level1;
if (s == "2") k |= verbose_t::level2;
if (s == "all" || s == "-1") k |= verbose_t::all;
if (s == "error") k |= verbose_t::error;
if (s == "check")
k |= verbose_t::create_check | verbose_t::exec_check;
if (s == "dispatch") k |= verbose_t::create_dispatch;
if (s == "profile")
k |= verbose_t::create_profile | verbose_t::exec_profile;
if (s == "profile_create") k |= verbose_t::create_profile;
if (s == "profile_exec") k |= verbose_t::exec_profile;
if (s == "profile_externals") k |= verbose_t::profile_externals;
if (s == "warn") k |= verbose_t::warn;
if (s.rfind("debuginfo=", 0) == 0)
k |= verbose_t::make_debuginfo(
std::strtol(s.c_str() + 10, nullptr, 10));
};
auto update_filter = [&](const std::string &s) -> int {
int k = component_t::none;
try {
std::regex regexp = std::regex(s);
#define REGEX_SEARCH(k, component, regexp) \
if (std::regex_search("" #component "", regexp)) { \
(k) |= component_t::component; \
filter_status().components += "" #component ","; \
}
REGEX_SEARCH(k, primitive, regexp);
REGEX_SEARCH(k, reorder, regexp);
REGEX_SEARCH(k, shuffle, regexp);
REGEX_SEARCH(k, concat, regexp);
REGEX_SEARCH(k, sum, regexp);
REGEX_SEARCH(k, convolution, regexp);
REGEX_SEARCH(k, deconvolution, regexp);
REGEX_SEARCH(k, eltwise, regexp);
REGEX_SEARCH(k, lrn, regexp);
REGEX_SEARCH(k, batch_normalization, regexp);
REGEX_SEARCH(k, inner_product, regexp);
REGEX_SEARCH(k, rnn, regexp);
REGEX_SEARCH(k, binary, regexp);
REGEX_SEARCH(k, matmul, regexp);
REGEX_SEARCH(k, resampling, regexp);
REGEX_SEARCH(k, pooling, regexp);
REGEX_SEARCH(k, reduction, regexp);
REGEX_SEARCH(k, prelu, regexp);
REGEX_SEARCH(k, softmax, regexp);
REGEX_SEARCH(k, layer_normalization, regexp);
REGEX_SEARCH(k, group_normalization, regexp);
REGEX_SEARCH(k, graph, regexp);
REGEX_SEARCH(k, gemm_api, regexp);
REGEX_SEARCH(k, ukernel, regexp);
#undef REGEX_SEARCH
} catch (const std::exception &e) {
filter_status().status = filter_status_t::flags::invalid;
filter_status().err_msg = e.what();
return component_t::all;
}
if (!filter_status().components.empty()) {
filter_status().components.pop_back();
filter_status().status = filter_status_t::flags::valid;
} else {
filter_status().status = filter_status_t::flags::invalid;
filter_status().err_msg
= "component with name \'" + s + "\' not found";
}
return k;
};
int val = verbose_t::error;
for (size_t pos_st = 0, pos_en = user_opt.find_first_of(',', pos_st);
true; pos_st = pos_en + 1,
pos_en = user_opt.find_first_of(',', pos_st)) {
std::string tok = user_opt.substr(pos_st, pos_en - pos_st);
update_kind(tok, val);
if (tok.rfind("filter=", 0) == 0) {
auto filter_str = tok.substr(7);
if (!filter_str.empty()) { flags = update_filter(filter_str); }
}
if (pos_en == std::string::npos) break;
}
verbose.set(val);
#ifdef DNNL_EXPERIMENTAL_LOGGING
const log_manager_t &log_manager = log_manager_t::get_log_manager();
if (log_manager.is_logger_enabled())
log_manager.set_log_level(user_opt);
#endif
}
int result = verbose.get() & verbosity_kind;
if (verbosity_kind == verbose_t::debuginfo)
result = verbose_t::get_debuginfo(verbose.get());
bool filter_result = flags & filter_kind;
return filter_result ? result : 0;
}
static setting_t<bool> verbose_timestamp {false};
bool get_verbose_timestamp() {
#if defined(DISABLE_VERBOSE)
return false;
#endif
if (verbose.get() == 0) return false;
if (!verbose_timestamp.initialized()) {
static bool val
= getenv_int_user("VERBOSE_TIMESTAMP", verbose_timestamp.get());
verbose_timestamp.set(val);
}
return verbose_timestamp.get();
}
std::ostream &operator<<(std::ostream &ss, engine_kind_t eng_kind) {
ss << dnnl_engine_kind2str(eng_kind);
return ss;
}
std::ostream &operator<<(std::ostream &ss, const engine_t *engine) {
ss << dnnl_engine_kind2str(engine->kind());
if (dnnl_engine_get_count(engine->kind()) > 1)
ss << ":" + std::to_string(engine->index());
return ss;
}
const char *prim_kind2str(primitive_kind_t prim_kind) {
switch ((int)prim_kind) {
case primitive_kind::zero_pad: return "zero_pad";
default: return dnnl_prim_kind2str(prim_kind);
}
}
std::ostream &operator<<(std::ostream &ss, primitive_kind_t prim_kind) {
ss << prim_kind2str(prim_kind);
return ss;
}
std::ostream &operator<<(std::ostream &ss, prop_kind_t prop_kind) {
ss << dnnl_prop_kind2str(prop_kind);
return ss;
}
std::ostream &operator<<(std::ostream &ss, data_type_t data_type) {
ss << dnnl_dt2str(data_type);
return ss;
}
std::ostream &operator<<(std::ostream &ss, alg_kind_t alg) {
ss << dnnl_alg_kind2str(alg);
return ss;
}
std::ostream &operator<<(std::ostream &ss, format_kind_t format_kind) {
ss << dnnl_fmt_kind2str(format_kind);
return ss;
}
std::ostream &operator<<(std::ostream &ss, sparse_encoding_t encoding) {
ss << dnnl_sparse_encoding2str(encoding);
return ss;
}
std::string normalization_flags2str(unsigned flags) {
std::string s;
if (flags & normalization_flags::use_global_stats) s += "G";
if (flags & normalization_flags::use_scale) s += "C";
if (flags & normalization_flags::use_shift) s += "H";
if (flags & normalization_flags::fuse_norm_relu) s += "R";
if (flags & normalization_flags::fuse_norm_add_relu) s += "A";
if (flags & normalization_flags::rms_norm) s += "M";
return s;
}
std::string rnn_flags2str(unsigned flags) {
std::string s;
if (flags & rnn_flags::diff_weights_overwrite) s += "O";
return s;
}
std::string cublasltfmt2str(const memory_desc_t *md) {
if (md->format_desc.cublaslt_blocked_desc.cublaslt_format
== cublaslt_memory_format_t::col32_2r_4r4) {
return ":col32_2r_4r4";
}
return "";
}
std::ostream &operator<<(std::ostream &ss, const memory_extra_desc_t &extra) {
using namespace memory_extra_flags;
ss << ":f" << extra.flags;
if (extra.flags & compensation_conv_s8s8)
ss << ":s8m" << extra.compensation_mask;
if (extra.flags & compensation_conv_asymmetric_src)
ss << ":zpm" << extra.asymm_compensation_mask;
if (extra.flags & compensation_gpu_conv_asymmetric_src) {
ss << ":zid" << extra.idhw[0];
ss << ":zih" << extra.idhw[1];
ss << ":ziw" << extra.idhw[2];
ss << ":zod" << extra.odhw[0];
ss << ":zoh" << extra.odhw[1];
ss << ":zow" << extra.odhw[2];
ss << ":zpd" << extra.pdhw[0];
ss << ":zph" << extra.pdhw[1];
ss << ":zpw" << extra.pdhw[2];
ss << ":zdd" << extra.ddhw[0];
ss << ":zdh" << extra.ddhw[1];
ss << ":zdw" << extra.ddhw[2];
ss << ":zs" << extra.dst_size;
}
if (extra.flags & scale_adjust && extra.scale_adjust != 1.f)
ss << ":sa" << extra.scale_adjust;
return ss;
}
std::string md2fmt_tag_str(const memory_desc_t *md) {
memory_desc_wrapper mdw(md);
if (mdw.has_runtime_strides()) return "*";
struct sort_key_t {
uint64_t stride_order;
dim_t outer_block;
int idx;
char dim_char;
};
dims_t blocks = {0};
mdw.compute_blocks(blocks);
std::vector<sort_key_t> sort_keys(mdw.ndims());
const auto &pdims = mdw.padded_dims();
const auto &blk = mdw.blocking_desc();
for (int i = 0; i < mdw.ndims(); ++i)
sort_keys[i] = {(uint64_t)(blk.strides[i] - 1), pdims[i] / blocks[i], i,
(char)((blocks[i] == 1 ? 'a' : 'A') + i)};
std::sort(sort_keys.begin(), sort_keys.end(),
[](const sort_key_t &left, const sort_key_t &right) {
if (left.stride_order < right.stride_order) return false;
if (left.stride_order == right.stride_order) {
if (left.outer_block < right.outer_block) return false;
if (left.outer_block == right.outer_block)
return left.idx < right.idx;
}
return true;
});
char dim_chars[DNNL_MAX_NDIMS + 1];
for (int i = 0; i < mdw.ndims(); ++i)
dim_chars[i] = sort_keys[i].dim_char;
dim_chars[mdw.ndims()] = '\0';
std::string s(dim_chars);
if (!mdw.is_plain()) {
for (int iblk = 0; iblk < blk.inner_nblks; ++iblk) {
char c = ('a' + (char)blk.inner_idxs[iblk]);
s += (std::to_string(blk.inner_blks[iblk]) + c);
}
}
return s;
}
std::string md2fmt_strides_str(const memory_desc_t *md) {
memory_desc_wrapper mdw(md);
std::string s;
if (mdw.has_runtime_dims_or_strides() || mdw.is_dense(true)) return s;
s += md2dim_str(md, dims_type_t::strides);
return s;
}
std::string md2fmt_str(
const char *name, const memory_desc_t *md, format_kind_t user_format) {
stringstream_t ss;
ss << name << ":";
if (!md || types::is_zero_md(md)) {
ss << data_type::undef << "::" << format_kind::undef << ":::";
return ss.str();
}
memory_desc_wrapper mdw(md);
ss << mdw.data_type() << ":";
bool padded_dims = false, padded_offsets = false;
for (int d = 0; d < mdw.ndims(); ++d) {
if (mdw.dims()[d] != mdw.padded_dims()[d]) padded_dims = true;
if (mdw.padded_offsets()[d] != 0) padded_offsets = true;
}
bool offset0 = mdw.offset0();
ss << (user_format == format_kind::any ? "a" : "");
ss << (padded_dims ? "p" : "");
ss << (padded_offsets ? "o" : "");
ss << (offset0 ? "0" : "");
ss << ":" << mdw.format_kind();
switch (static_cast<int>(mdw.format_kind())) {
case format_kind::blocked:
ss << ":" << md2fmt_tag_str(md) << ":" << md2fmt_strides_str(md);
break;
case format_kind::cublaslt_blocked: ss << cublasltfmt2str(md); break;
case format_kind::wino:
case format_kind::rnn_packed:
case format_kind::opaque: ss << "::"; break;
case format_kind::sparse: ss << ":" << mdw.encoding() << ":"; break;
case format_kind::any: ss << ":any:"; break;
default:
assert(!"unsupported format_kind");
ss << "::";
break;
}
ss << mdw.extra();
return ss.str();
}
std::ostream &operator<<(std::ostream &ss, const memory_desc_t *md) {
assert(!"unexpected call to the operator<<");
return ss;
}
template <typename T>
static std::string get_val_str(T val) {
static_assert(
std::is_arithmetic<T>::value, "T must be an arithmetic type.");
if (is_runtime_value(val)) return std::string("*");
return std::to_string(val);
}
std::string md2dim_str(const memory_desc_t *md, dims_type_t dims_type) {
if (md == nullptr || md->ndims == 0) return "";
memory_desc_wrapper mdw(md);
std::string s;
assert(dims_type == dims_type_t::dims || dims_type == dims_type_t::strides);
const auto &dims_obj
= dims_type == dims_type_t::dims ? mdw.dims() : mdw.strides();
s += get_val_str(dims_obj[0]);
for (int d = 1; d < mdw.ndims(); ++d)
s += ("x" + get_val_str(dims_obj[d]));
return s;
}
std::string md2desc_str(const memory_desc_t *md) {
const auto dims = md->dims;
std::string s;
if (md->ndims >= 6) return md2dim_str(md);
if (md->ndims == 1) {
s += "x" + std::to_string(dims[0]);
return s;
}
s += "mb" + std::to_string(dims[0]) + "ic" + std::to_string(dims[1]);
if (md->ndims >= 5) s += "id" + std::to_string(dims[md->ndims - 3]);
if (md->ndims >= 4) s += "ih" + std::to_string(dims[md->ndims - 2]);
if (md->ndims >= 3) s += "iw" + std::to_string(dims[md->ndims - 1]);
return s;
}
std::ostream &operator<<(
std::ostream &ss, const rnn_create_time_scales_t &rnn_scales) {
ss << rnn_scales.mask_;
const float val = rnn_scales.scales_[0];
if (rnn_scales.mask_ == 0 || is_runtime_value(val))
ss << ":" << get_val_str(val);
return ss;
}
namespace {
int get_runtime_mask(const memory_desc_t *md) {
int mask = 0;
for (int d = md->ndims - 1; d >= 0; --d) {
mask += is_runtime_value(md->dims[d]) ? 1 << d : 0;
}
return mask;
}
int get_arg_index(int arg) {
if (arg & DNNL_ARG_MULTIPLE_SRC) return arg - DNNL_ARG_MULTIPLE_SRC;
switch (arg) {
case DNNL_ARG_SRC_0: return 0;
case DNNL_ARG_SRC_1: return 1;
case DNNL_ARG_SRC_2: return 2;
default: return -1;
}
return -1;
}
std::string get_arg(int arg) {
if (arg & DNNL_ARG_MULTIPLE_SRC) return "msrc";
std::string s;
switch (arg) {
case DNNL_ARG_SRC: case DNNL_ARG_SRC_1:
case DNNL_ARG_SRC_2: s = "src"; break;
case DNNL_ARG_DST: s = "dst"; break;
case DNNL_ARG_WEIGHTS: case DNNL_ARG_WEIGHTS_1:
case DNNL_ARG_WEIGHTS_2: s = "wei"; break;
case DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_DST:
s = "attr_post_op_dw_dst";
break;
case DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_WEIGHTS:
s = "attr_post_op_dw_wei";
break;
default: assert(!"unsupported arg"); s = "unsupported arg";
}
return s;
}
}
std::string arg2str(int arg) {
std::string s = get_arg(arg);
const int idx = get_arg_index(arg);
if (idx != -1) s += std::to_string(idx);
return s;
}
std::ostream &operator<<(std::ostream &ss, const primitive_attr_t *attr) {
struct {
const char *operator()() {
current[0] = next;
next = ' ';
return current;
}
private:
char current[2] = {};
char next = 0;
} field_delim;
std::string empty_delim, attr_delim = "+";
const scratchpad_mode_t &spm = attr->scratchpad_mode_;
if (spm != scratchpad_mode_t::dnnl_scratchpad_mode_library) {
ss << field_delim()
<< "attr-scratchpad:" << dnnl_scratchpad_mode2str(spm);
}
const fpmath_t &fpm = attr->fpmath_;
if (fpm.mode_ != fpmath_mode_t::dnnl_fpmath_mode_strict
|| fpm.apply_to_int_) {
ss << field_delim()
<< "attr-fpmath:" << dnnl_fpmath_mode2str(fpm.mode_);
if (fpm.apply_to_int_) ss << ":true";
}
const accumulation_mode_t &am = attr->acc_mode_;
if (am != accumulation_mode::strict) {
ss << field_delim()
<< "attr-acc-mode:" << dnnl_accumulation_mode2str(am);
}
const auto &rm = attr->rounding_mode_;
if (!rm.has_default_values()) {
std::string delim = empty_delim;
ss << field_delim() << "attr-rounding-mode:";
for (const auto &e : rm.rounding_modes_map_) {
if (!rm.has_default_values(e.first))
ss << delim << arg2str(e.first) << ":"
<< dnnl_rounding_mode2str(e.second);
delim = attr_delim;
}
}
const bool deterministic = attr->deterministic_;
if (deterministic) {
ss << field_delim() << "attr-deterministic:" << deterministic;
}
if (attr->has_default_values()) return ss;
const scales_t &scales = attr->scales_;
if (!scales.has_default_values()) {
ss << field_delim() << "attr-scales:" << scales.get_verbose();
}
const zero_points_t &zero_points = attr->zero_points_;
if (!zero_points.has_default_values()) {
ss << field_delim() << "attr-zero-points:" << zero_points.get_verbose();
}
const precomputed_reductions_t &pr = attr->precomputed_reductions_;
if (!pr.has_default_values()) {
ss << field_delim()
<< "attr-precomputed-reductions:" << pr.get_verbose();
}
const post_ops_t &po = attr->post_ops_;
if (!po.has_default_values()) {
std::string delim = empty_delim;
ss << field_delim() << "attr-post-ops:";
for (int i = 0; i < po.len(); ++i) {
const post_ops_t::entry_t &e = po.entry_[i];
switch (e.kind) {
case primitive_kind::sum: {
const auto &s = e.sum;
ss << delim << "sum";
if (s.scale != 1.f || s.zero_point != 0
|| s.dt != data_type::undef)
ss << ":" << s.scale;
if (s.zero_point != 0 || s.dt != data_type::undef)
ss << ":" << s.zero_point;
if (s.dt != data_type::undef) ss << ":" << s.dt;
} break;
case primitive_kind::convolution: {
using namespace data_type;
const auto &c = e.depthwise_conv;
ss << delim << "dw:k" << c.kernel << "s" << c.stride << "p"
<< c.padding;
if (c.wei_dt == s8 || c.dst_dt != f32)
ss << ":" << c.dst_dt;
} break;
case primitive_kind::eltwise: {
const post_ops_t::entry_t::eltwise_t &ew = e.eltwise;
ss << delim << ew.alg;
if (ew.alpha != 0.f || ew.beta != 0.f || ew.scale != 1.f)
ss << ":" << ew.alpha;
if (ew.beta != 0.f || ew.scale != 1.f) ss << ":" << ew.beta;
if (ew.scale != 1.f) ss << ":" << ew.scale;
} break;
case primitive_kind::binary: {
const post_ops_t::entry_t::binary_t &eb = e.binary;
const auto &md = eb.user_src1_desc;
int mask = 0;
for (int d = 0; d < md.ndims; ++d)
mask += md.dims[d] != 1 ? (1 << d) : 0;
ss << delim << eb.alg << ":" << md.data_type << ":" << mask;
const memory_desc_wrapper mdw(md);
switch (mdw.format_kind()) {
case format_kind::blocked:
if (!mdw.count_non_unit_dims(1)) {
ss << ":" << md2fmt_tag_str(&eb.src1_desc);
const auto &strides_str
= md2fmt_strides_str(&eb.src1_desc);
if (!strides_str.empty())
ss << ":" << strides_str;
}
break;
case format_kind::any: ss << ":any"; break;
default: assert(!"unsupported format_kind");
}
} break;
case primitive_kind::prelu: {
const auto &ep = e.prelu;
ss << delim << "prelu" << ":" << ep.mask;
} break;
default: assert(!"unsupported post op primitive kind!"); break;
}
delim = attr_delim;
}
}
const rnn_data_qparams_t &rnn_qp = attr->rnn_data_qparams_;
if (!rnn_qp.has_default_values()) {
ss << field_delim() << "rnn_data_qparams:" << rnn_qp.scale_ << ":"
<< rnn_qp.shift_ << ";";
}
if (!attr->dropout_.has_default_values()) {
ss << field_delim() << "attr-dropout";
const memory_desc_wrapper mdw(attr->dropout_.user_dropout_desc_);
switch (mdw.format_kind()) {
case format_kind::blocked:
if (!mdw.count_non_unit_dims(1))
ss << ":" << md2fmt_tag_str(&attr->dropout_.dropout_desc_);
break;
case format_kind::any: ss << ":any"; break;
case format_kind::undef: ss << ":undef"; break;
default: assert(!"unsupported format_kind");
}
ss << ":" << dnnl_dt2str(attr->dropout_.seed_dt_);
ss << ":" << attr->dropout_.use_offset_;
ss << ":" << attr->dropout_.use_host_scalars_;
}
return ss;
}
std::string attr2str(const primitive_attr_t *attr) {
stringstream_t ss;
ss << attr;
return ss.str();
}
namespace {
template <typename pd_t>
std::string init_info_batch_normalization(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->src_md();
ss << md2fmt_str("data", src_md, pd->src_md(0, true)->format_kind);
if (!pd->is_fwd()) {
ss << " "
<< md2fmt_str("diff", pd->diff_src_md(0),
pd->diff_src_md(0, true)->format_kind);
}
ss << "," << pd->attr() << ",";
ss << "flags:" << normalization_flags2str(pd->desc()->flags) << ",";
ss << md2desc_str(src_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_binary(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
auto src0_md = pd->invariant_src_md(0);
auto src1_md = pd->invariant_src_md(1);
auto src2_md = pd->invariant_src_md(2);
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("src", src0_md, pd->invariant_src_user_format_kind(0))
<< " ";
ss << md2fmt_str("src", src1_md, pd->invariant_src_user_format_kind(1))
<< " ";
if (pd->desc()->alg_kind == alg_kind_t::dnnl_binary_select) {
ss << md2fmt_str("src", src2_md, pd->invariant_src_user_format_kind(2))
<< " ";
}
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << ",";
ss << md2dim_str(src0_md) << ":" << md2dim_str(src1_md);
if (pd->desc()->alg_kind == alg_kind_t::dnnl_binary_select)
ss << ":" << md2dim_str(src2_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_concat(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
for (int i = 0; i < pd->n_inputs(); ++i) {
auto src_i_md = pd->invariant_src_md(i);
ss << md2fmt_str("src", src_i_md, pd->invariant_src_user_format_kind(i))
<< " ";
}
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",";
ss << "axis:" << pd->desc()->concat_dimension << ",";
for (int i = 0; i < pd->n_inputs(); ++i) {
auto src_i_md = pd->src_md(i);
ss << md2dim_str(src_i_md);
if (i < pd->n_inputs() - 1) ss << ":";
}
return ss.str();
}
template <typename pd_t>
std::string init_info_convolution(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->invariant_src_md();
auto wei_md = pd->invariant_wei_md();
auto bia_md = pd->invariant_bia_md();
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("src", src_md, pd->invariant_src_user_format_kind())
<< " ";
ss << md2fmt_str("wei", wei_md, pd->invariant_wei_user_format_kind())
<< " ";
ss << md2fmt_str("bia", bia_md, pd->invariant_bia_user_format_kind())
<< " ";
const bool has_fused_dw
= pd->attr()->post_ops_.find(primitive_kind::convolution) >= 0;
if (has_fused_dw) {
auto src_fused_md = pd->arg_md(DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_SRC);
auto wei_fused_md
= pd->arg_md(DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_WEIGHTS);
auto bia_fused_md
= pd->arg_md(DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_BIAS);
ss << md2fmt_str("src_fused", src_fused_md,
pd->invariant_dst_user_format_kind(
DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_SRC))
<< " ";
ss << md2fmt_str("wei_fused", wei_fused_md, format_kind::undef) << " ";
ss << md2fmt_str("bia_fused", bia_fused_md, format_kind::undef) << " ";
ss << md2fmt_str("dst", dst_md, format_kind::undef);
} else {
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
}
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << ",";
if (pd->with_groups()) ss << "g" << pd->G();
ss << "mb" << pd->MB() << "_" << "ic" << pd->IC() << "oc" << pd->OC()
<< "_";
if (pd->ndims() >= 5)
ss << "id" << pd->ID() << "od" << (has_fused_dw ? pd->ID() : pd->OD())
<< "kd" << pd->KD() << "sd" << pd->KSD() << "dd" << pd->KDD() << "pd"
<< pd->padFront() << "_";
if (pd->ndims() >= 4)
ss << "ih" << pd->IH() << "oh" << (has_fused_dw ? pd->IH() : pd->OH())
<< "kh" << pd->KH() << "sh" << pd->KSH() << "dh" << pd->KDH() << "ph"
<< pd->padT() << "_";
ss << "iw" << pd->IW() << "ow" << (has_fused_dw ? pd->IW() : pd->OW())
<< "kw" << pd->KW() << "sw" << pd->KSW() << "dw" << pd->KDW() << "pw"
<< pd->padL();
return ss.str();
}
template <typename pd_t>
std::string init_info_deconvolution(const engine_t *e, const pd_t *pd) {
return init_info_convolution(e, pd);
}
template <typename pd_t>
std::string init_info_eltwise(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto data_md = pd->use_dst() ? pd->dst_md(0) : pd->src_md(0);
auto user_data_format_kind = pd->use_dst()
? pd->dst_md(0, true)->format_kind
: pd->src_md(0, true)->format_kind;
auto diff_src_md = pd->diff_src_md();
ss << md2fmt_str("data", data_md, user_data_format_kind);
if (!pd->is_fwd()) {
ss << " "
<< md2fmt_str("diff", diff_src_md,
pd->invariant_src_user_format_kind(0));
}
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << " alpha:" << pd->desc()->alpha
<< " beta:" << pd->desc()->beta << ",";
ss << md2dim_str(data_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_gated_mlp(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
ss << md2fmt_str("src", pd->arg_md(DNNL_ARG_SRC), format_kind::undef)
<< " ";
ss << md2fmt_str(
"wei_gate", pd->arg_md(DNNL_ARG_WEIGHTS_GATE), format_kind::undef)
<< " ";
ss << md2fmt_str(
"wei_up", pd->arg_md(DNNL_ARG_WEIGHTS_UP), format_kind::undef)
<< " ";
ss << md2fmt_str(
"wei_down", pd->arg_md(DNNL_ARG_WEIGHTS_DOWN), format_kind::undef)
<< " ";
ss << md2fmt_str("dst", pd->arg_md(DNNL_ARG_DST), format_kind::undef);
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->activation() << ",";
ss << "mb" << pd->MB() << "ic" << pd->IC() << "oc" << pd->OC();
return ss.str();
}
template <typename pd_t>
std::string init_info_gemm(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
auto src_a_md = pd->invariant_src_md(0);
auto src_b_md = pd->invariant_src_md(1);
auto bia_md = pd->invariant_bia_md();
auto dst_md = pd->invariant_dst_md();
auto get_bia_mask = [&bia_md]() {
auto bia_ndims = bia_md->ndims;
auto bia_dims = bia_md->dims;
int mask = 0;
for (int d = bia_ndims - 1; d >= 0; --d) {
mask += bia_dims[d] != 1 ? 1 << d : 0;
}
return mask;
};
ss << md2fmt_str("src_a", src_a_md, pd->invariant_src_user_format_kind(0))
<< " ";
ss << md2fmt_str("src_b", src_b_md, pd->invariant_src_user_format_kind(1))
<< " ";
if (pd->with_bias()) {
ss << md2fmt_str("bia", bia_md, pd->invariant_bia_user_format_kind());
ss << "_mask" << get_bia_mask();
ss << " ";
}
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",,";
ss << md2dim_str(src_a_md) << ":" << md2dim_str(src_b_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_group_normalization(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->src_md();
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("src", src_md, pd->src_md(0, true)->format_kind) << " ";
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
if (!pd->is_fwd()) {
ss << " "
<< md2fmt_str("diff_src", pd->diff_src_md(0),
pd->diff_src_md(0, true)->format_kind);
}
ss << "," << pd->attr() << ",";
ss << "flags:" << normalization_flags2str(pd->desc()->flags) << ",";
ss << "g" << pd->desc()->groups << md2desc_str(src_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_inner_product(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->invariant_src_md();
auto wei_md = pd->invariant_wei_md();
auto bia_md = pd->invariant_bia_md();
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("src", src_md, pd->invariant_src_user_format_kind())
<< " ";
ss << md2fmt_str("wei", wei_md, pd->invariant_wei_user_format_kind())
<< " ";
ss << md2fmt_str("bia", bia_md, pd->invariant_bia_user_format_kind())
<< " ";
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",,";
ss << md2desc_str(src_md);
ss << "oc" << pd->OC();
return ss.str();
}
template <typename pd_t>
std::string init_info_layer_normalization(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->src_md();
auto dst_md = pd->invariant_dst_md();
auto stats_md = pd->is_fwd() && !pd->stats_are_src() ? pd->dst_md(1)
: pd->src_md(1);
auto user_stats_format_kind = pd->is_fwd() && !pd->stats_are_src()
? pd->dst_md(1, true)->format_kind
: pd->src_md(1, true)->format_kind;
auto scaleshift_md = pd->weights_md(0);
auto diff_scaleshift_md = pd->diff_weights_md(0);
ss << md2fmt_str("src", src_md, pd->src_md(0, true)->format_kind) << " ";
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind())
<< " ";
ss << md2fmt_str("stats", stats_md, user_stats_format_kind);
if (pd->use_scale()) {
ss << " "
<< md2fmt_str("scale", scaleshift_md,
pd->weights_md(0, true)->format_kind);
}
if (pd->use_shift()) {
ss << " "
<< md2fmt_str("shift", scaleshift_md,
pd->weights_md(0, true)->format_kind);
}
if (!pd->is_fwd()) {
ss << " "
<< md2fmt_str("diff_src", pd->diff_src_md(0),
pd->diff_src_md(0, true)->format_kind);
}
if (!pd->is_fwd() && pd->use_scale()) {
ss << " "
<< md2fmt_str("diff_scale", diff_scaleshift_md,
pd->diff_weights_md(0, true)->format_kind);
}
if (!pd->is_fwd() && pd->use_shift()) {
ss << " "
<< md2fmt_str("diff_shift", diff_scaleshift_md,
pd->diff_weights_md(0, true)->format_kind);
}
ss << "," << pd->attr() << ",";
ss << "flags:" << normalization_flags2str(pd->desc()->flags) << ",";
ss << md2dim_str(src_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_lrn(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto data_md = pd->src_md();
auto diff_src_md = pd->diff_src_md();
ss << md2fmt_str("data", data_md, pd->src_md(0, true)->format_kind);
if (!pd->is_fwd()) {
ss << " "
<< md2fmt_str("diff", diff_src_md,
pd->invariant_src_user_format_kind(0));
}
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << ",";
ss << md2desc_str(data_md);
ss << "ls" << pd->desc()->local_size << "beta" << pd->desc()->lrn_beta;
return ss.str();
}
std::string mds2str_matmul(const memory_desc_t *src_md,
format_kind_t src_user_format_kind, const memory_desc_t *wei_md,
format_kind_t wei_user_format_kind, const memory_desc_t *bia_md,
format_kind_t bia_user_format_kind, const memory_desc_t *dst_md,
format_kind_t dst_user_format_kind) {
auto get_bia_mask = [&bia_md]() {
auto bia_ndims = bia_md->ndims;
auto bia_dims = bia_md->dims;
int mask = 0;
for (int d = bia_ndims - 1; d >= 0; --d) {
mask += bia_dims[d] != 1 ? 1 << d : 0;
}
return mask;
};
stringstream_t ss;
ss << md2fmt_str("src", src_md, src_user_format_kind) << " ";
ss << md2fmt_str("wei", wei_md, wei_user_format_kind) << " ";
if (!memory_desc_wrapper(bia_md).is_zero()) {
ss << md2fmt_str("bia", bia_md, bia_user_format_kind);
ss << "_mask" << get_bia_mask();
ss << " ";
}
ss << md2fmt_str("dst", dst_md, dst_user_format_kind);
std::string s = ss.str();
return s;
}
std::string dims2fmt_str_matmul(
const memory_desc_t *src_md, const memory_desc_t *wei_md) {
return md2dim_str(src_md) + ":" + md2dim_str(wei_md);
}
template <typename pd_t>
std::string init_info_matmul(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
auto src_md = pd->invariant_src_md();
auto wei_md = pd->invariant_wei_md();
auto bia_md = pd->invariant_bia_md();
auto dst_md = pd->invariant_dst_md();
ss << mds2str_matmul(src_md, pd->invariant_src_user_format_kind(), wei_md,
pd->invariant_wei_user_format_kind(), bia_md,
pd->invariant_bia_user_format_kind(), dst_md,
pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",";
if (pd->has_runtime_dims_or_strides()) {
ss << "runtime_dims_masks:" << get_runtime_mask(src_md) << ":"
<< get_runtime_mask(wei_md);
}
ss << "," << dims2fmt_str_matmul(src_md, wei_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_pooling(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->invariant_src_md();
auto dst_md = pd->invariant_dst_md();
auto ws_md = pd->workspace_md();
ss << md2fmt_str("src", src_md, pd->invariant_src_user_format_kind())
<< " ";
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
if (!memory_desc_wrapper(ws_md).is_zero()) {
ss << " " << md2fmt_str("ws", ws_md, format_kind::undef);
}
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << ",";
ss << "mb" << pd->MB() << "ic" << pd->IC() << "_";
if (pd->ndims() >= 5)
ss << "id" << pd->ID() << "od" << pd->OD() << "kd" << pd->KD() << "sd"
<< pd->KSD() << "dd" << pd->KDD() << "pd" << pd->padFront() << "_";
if (pd->ndims() >= 4)
ss << "ih" << pd->IH() << "oh" << pd->OH() << "kh" << pd->KH() << "sh"
<< pd->KSH() << "dh" << pd->KDH() << "ph" << pd->padT() << "_";
ss << "iw" << pd->IW() << "ow" << pd->OW() << "kw" << pd->KW() << "sw"
<< pd->KSW() << "dw" << pd->KDW() << "pw" << pd->padL();
return ss.str();
}
template <typename pd_t>
std::string init_info_prelu(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto data_md = pd->src_md(0);
auto wei_md = pd->weights_md(0);
auto diff_data_md = pd->diff_src_md(0);
auto diff_wei_md = pd->diff_weights_md(0);
ss << md2fmt_str("data", data_md, pd->src_md(0, true)->format_kind) << " ";
ss << md2fmt_str("wei", wei_md, pd->weights_md(0, true)->format_kind);
if (!memory_desc_wrapper(diff_data_md).is_zero()) {
ss << " "
<< md2fmt_str("diff", diff_data_md,
pd->diff_src_md(0, true)->format_kind);
}
if (!memory_desc_wrapper(diff_wei_md).is_zero()) {
ss << " "
<< md2fmt_str("diff_wei", diff_wei_md,
pd->diff_weights_md(0, true)->format_kind);
}
ss << "," << pd->attr() << ",,";
ss << md2dim_str(data_md) << ":" << md2dim_str(wei_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_reduction(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
auto src_md = pd->invariant_src_md();
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("src", src_md, pd->invariant_src_user_format_kind())
<< " ";
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << " p:" << pd->desc()->p
<< " eps:" << pd->desc()->eps << ",";
ss << md2dim_str(src_md) << ":" << md2dim_str(dst_md);
return ss.str();
}
std::string mds2str_reorder(const memory_desc_t *src_md,
format_kind_t src_user_format_kind, const memory_desc_t *dst_md,
format_kind_t dst_user_format_kind) {
std::string s;
s += md2fmt_str("src", src_md, src_user_format_kind);
s += " ";
s += md2fmt_str("dst", dst_md, dst_user_format_kind);
return s;
}
std::string dims2fmt_str_reorder(const memory_desc_t *src_md) {
return md2dim_str(src_md);
}
template <typename pd_t>
std::string init_info_reorder(const engine_t *e, pd_t *pd) {
stringstream_t ss;
const auto src_ek = pd->desc()->src_engine_kind;
const auto dst_ek = pd->desc()->dst_engine_kind;
if (src_ek != dst_ek)
ss << src_ek << "2" << dst_ek;
else
ss << e;
ss << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
auto src_md = pd->invariant_src_md();
auto dst_md = pd->invariant_dst_md();
ss << mds2str_reorder(src_md, pd->invariant_src_user_format_kind(), dst_md,
pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",";
if (pd->has_runtime_dims_or_strides()) {
ss << "runtime-dim-mask:" << get_runtime_mask(src_md);
}
ss << "," << dims2fmt_str_reorder(src_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_resampling(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->invariant_src_md();
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("src", src_md, pd->invariant_src_user_format_kind())
<< " ";
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->desc()->alg_kind << ",";
ss << "mb" << pd->MB() << "ic" << pd->C() << "_";
if (pd->ndims() >= 5) ss << "id" << pd->ID() << "od" << pd->OD() << "_";
if (pd->ndims() >= 4) ss << "ih" << pd->IH() << "oh" << pd->OH() << "_";
ss << "iw" << pd->IW() << "ow" << pd->OW();
return ss.str();
}
template <typename pd_t>
std::string init_info_rnn(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
ss << md2fmt_str(
"src_layer", pd->src_md(0), pd->src_md(0, true)->format_kind)
<< " ";
if (pd->with_src_iter())
ss << md2fmt_str(
"src_iter", pd->src_md(1), pd->src_md(1, true)->format_kind)
<< " ";
ss << md2fmt_str("wei_layer", pd->weights_md(0),
pd->weights_md(0, true)->format_kind)
<< " ";
ss << md2fmt_str(
"wei_iter", pd->weights_md(1), pd->weights_md(1, true)->format_kind)
<< " ";
if (pd->is_lstm_peephole())
ss << md2fmt_str("wei_peephole", pd->weights_md(2),
pd->weights_md(2, true)->format_kind)
<< " ";
if (pd->is_lstm_projection()) {
auto proj_idx = 2 + pd->is_lstm_peephole();
ss << md2fmt_str("wei_proj", pd->weights_md(proj_idx),
pd->weights_md(proj_idx, true)->format_kind)
<< " ";
}
if (pd->with_bias()) {
auto bias_idx = 2 + pd->is_lstm_peephole() + pd->is_lstm_projection();
ss << md2fmt_str("bias", pd->weights_md(bias_idx),
pd->weights_md(bias_idx, true)->format_kind)
<< " ";
}
ss << md2fmt_str(
"dst_layer", pd->dst_md(0), pd->dst_md(0, true)->format_kind);
if (pd->with_dst_iter())
ss << " "
<< md2fmt_str("dst_iter", pd->dst_md(1),
pd->dst_md(1, true)->format_kind);
if (!pd->is_fwd()) {
ss << " ";
ss << md2fmt_str("diff_src_layer", pd->diff_src_md(0),
pd->diff_src_md(0, true)->format_kind)
<< " ";
if (pd->with_src_iter())
ss << md2fmt_str("diff_src_iter", pd->diff_src_md(1),
pd->diff_src_md(1, true)->format_kind)
<< " ";
ss << md2fmt_str("diff_wei_layer", pd->diff_weights_md(0),
pd->diff_weights_md(0, true)->format_kind)
<< " ";
ss << md2fmt_str("diff_wei_iter", pd->diff_weights_md(1),
pd->diff_weights_md(1, true)->format_kind)
<< " ";
if (pd->is_lstm_peephole())
ss << md2fmt_str("diff_wei_peephole", pd->diff_weights_md(2),
pd->diff_weights_md(2, true)->format_kind)
<< " ";
if (pd->is_lstm_projection()) {
auto proj_idx = 2 + pd->is_lstm_peephole();
ss << md2fmt_str("diff_wei_proj", pd->weights_md(proj_idx),
pd->weights_md(proj_idx, true)->format_kind)
<< " ";
}
if (pd->with_bias()) {
auto bias_idx
= 2 + pd->is_lstm_peephole() + pd->is_lstm_projection();
ss << md2fmt_str("diff_bias", pd->weights_md(bias_idx),
pd->weights_md(bias_idx, true)->format_kind)
<< " ";
}
ss << md2fmt_str("diff_dst_layer", pd->diff_dst_md(0),
pd->diff_dst_md(0, true)->format_kind);
if (pd->with_dst_iter())
ss << " "
<< md2fmt_str("diff_dst_iter", pd->diff_dst_md(1),
pd->diff_dst_md(1, true)->format_kind);
}
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->cell_kind()
<< " direction:" << dnnl_rnn_direction2str(pd->direction())
<< " activation:" << pd->activation_kind()
<< " flags:" << rnn_flags2str(pd->desc()->flags) << ",";
ss << "l" << pd->L() << "t" << pd->T() << "mb" << pd->MB() << "sic"
<< pd->SIC() << "slc" << pd->SLC() << "dhc" << pd->DHC() << "dic"
<< pd->DIC();
return ss.str();
}
template <typename pd_t>
std::string init_info_shuffle(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto data_md = pd->invariant_src_md();
ss << md2fmt_str("data", data_md, pd->invariant_src_user_format_kind());
ss << "," << pd->attr() << ",";
ss << "axis:" << pd->axis() << " group:" << pd->group_size() << ",";
ss << md2dim_str(data_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_softmax(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
auto src_md = pd->invariant_src_md();
auto dst_md = pd->dst_md();
auto diff_dst_md = pd->diff_dst_md();
ss << md2fmt_str("src", src_md, pd->invariant_src_user_format_kind())
<< " ";
ss << md2fmt_str("dst", dst_md, pd->dst_md(0, true)->format_kind);
if (!types::is_zero_md(diff_dst_md)) {
ss << " "
<< md2fmt_str("diff_dst", diff_dst_md,
pd->diff_dst_md(0, true)->format_kind);
}
ss << "," << pd->attr() << ",";
ss << "alg:" << pd->alg_kind() << " axis:" << pd->axis() << ",";
ss << md2dim_str(src_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_sum(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << "," << prop_kind::undef
<< ",";
for (int i = 0; i < pd->n_inputs(); ++i) {
auto src_i_md = pd->invariant_src_md(i);
ss << md2fmt_str("src", src_i_md, pd->invariant_src_user_format_kind(i))
<< " ";
}
auto dst_md = pd->invariant_dst_md();
ss << md2fmt_str("dst", dst_md, pd->invariant_dst_user_format_kind());
ss << "," << pd->attr() << ",,";
ss << md2dim_str(dst_md);
return ss.str();
}
template <typename pd_t>
std::string init_info_sdpa(const engine_t *e, const pd_t *pd) {
stringstream_t ss;
ss << e << "," << pd->kind() << "," << pd->name() << ","
<< pd->desc()->prop_kind << ",";
const sdpa_desc_t *desc = pd->desc();
ss << md2fmt_str(
"query", desc->qry_md(), pd->invariant_src_user_format_kind(0))
<< " ";
ss << md2fmt_str(
"key", desc->key_md(), pd->invariant_src_user_format_kind(1))
<< " ";
ss << md2fmt_str(
"val", desc->val_md(), pd->invariant_src_user_format_kind(2))
<< " ";
if (pd->with_attn_mask())
ss << md2fmt_str("msk", desc->attn_mask_md(),
pd->invariant_src_user_format_kind(3))
<< " ";
ss << md2fmt_str("dst", pd->dst_md(), pd->invariant_dst_user_format_kind())
<< ",";
std::string delimiter;
if (pd->with_key_scales() || pd->with_value_scales()) {
ss << delimiter << "attr-scales:";
delimiter = "";
if (pd->with_key_scales()) {
ss << delimiter << "key:" << desc->kq_scales;
delimiter = "+";
}
if (pd->with_value_scales()) {
ss << delimiter << "val:" << desc->vs_scales;
delimiter = "+";
}
delimiter = " ";
}
if (pd->with_key_zp() || pd->with_value_zp()) {
ss << delimiter << "attr-zero-points:";
delimiter = "";
if (pd->with_key_zp()) {
ss << delimiter << "key:" << desc->kq_zero_points;
delimiter = "+";
}
if (pd->with_value_zp()) {
ss << delimiter << "val:" << desc->vs_zero_points;
delimiter = "+";
}
delimiter = " ";
}
ss << delimiter << pd->attr();
delimiter = " ";
ss << ",alg:" << desc->softmax_alg;
if (pd->with_attn_mask()) {
auto *md = desc->attn_mask_md();
ss << delimiter << "msk:" << (md->dims[2] == 1 ? 1 : 2) << 'd';
} else if (pd->with_causal_mask()) {
ss << delimiter;
if (desc->mask_type == attn_mask_type::top_left)
ss << "msk:causal:top_left";
else
ss << "msk:causal:bottom_right";
}
if (pd->with_attn_scale()) {
ss << delimiter << "scl:";
if (desc->invert_scale)
ss << "div:";
else
ss << "mul:";
ss << dnnl_dt2str(desc->scale_md()->data_type) << ":";
if (pd->with_host_scale())
ss << "host";
else
ss << "device";
}
ss << "," << md2dim_str(desc->qry_md()) << ":" << md2dim_str(desc->key_md())
<< ":" << md2dim_str(desc->val_md());
return ss.str();
}
}
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 s;
#if defined(DISABLE_VERBOSE)
return s;
#endif
switch ((int)prim_kind) {
case primitive_kind::matmul:
s = mds2str_matmul(src_md, format_kind::undef, wei_md,
format_kind::undef, bia_md, format_kind::undef, dst_md,
format_kind::undef);
break;
case primitive_kind::reorder:
s = mds2str_reorder(
src_md, format_kind::undef, dst_md, format_kind::undef);
break;
case primitive_kind::batch_normalization:
case primitive_kind::binary:
case primitive_kind::concat:
case primitive_kind::convolution:
case primitive_kind::deconvolution:
case primitive_kind::eltwise:
case primitive_kind::inner_product:
case primitive_kind::layer_normalization:
case primitive_kind::lrn:
case primitive_kind::pooling:
case primitive_kind::prelu:
case primitive_kind::reduction:
case primitive_kind::resampling:
case primitive_kind::rnn:
case primitive_kind::shuffle:
case primitive_kind::softmax:
case primitive_kind::sum: assert(!"unsupported primitive kind"); break;
default: assert(!"unknown primitive kind");
}
return s;
}
std::string prepend_identifier_and_version(const char *fmt_str) {
assert(std::string(fmt_str).find("onednn_verbose") == std::string::npos);
std::string s
= "onednn_verbose," + std::string(verbose_version) + "," + fmt_str;
return s;
}
void verbose_printf_impl(const char *raw_fmt_str, verbose_t::flag_kind kind) {
#if defined(DISABLE_VERBOSE)
return;
#endif
if (get_verbose(kind)) print_header();
const auto &fmt_str = prepend_identifier_and_version(raw_fmt_str);
#ifdef DNNL_EXPERIMENTAL_LOGGING
const log_manager_t &log_manager = log_manager_t::get_log_manager();
if (log_manager.is_logger_enabled())
log_manager.log(fmt_str.c_str(), align_verbose_mode_to_log_level(kind));
if (log_manager.is_console_enabled()) {
printf("%s", fmt_str.c_str());
fflush(stdout);
}
#else
printf("%s", fmt_str.c_str());
fflush(stdout);
#endif
}
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 s;
#if defined(DISABLE_VERBOSE)
return s;
#endif
switch ((int)prim_kind) {
case primitive_kind::matmul:
s = dims2fmt_str_matmul(src_md, wei_md);
break;
case primitive_kind::reorder: s = dims2fmt_str_reorder(src_md); break;
case primitive_kind::batch_normalization:
case primitive_kind::binary:
case primitive_kind::concat:
case primitive_kind::convolution:
case primitive_kind::deconvolution:
case primitive_kind::eltwise:
case primitive_kind::inner_product:
case primitive_kind::layer_normalization:
case primitive_kind::lrn:
case primitive_kind::pooling:
case primitive_kind::prelu:
case primitive_kind::reduction:
case primitive_kind::resampling:
case primitive_kind::rnn:
case primitive_kind::shuffle:
case primitive_kind::softmax:
case primitive_kind::sum: assert(!"unsupported primitive kind"); break;
default: assert(!"unknown primitive kind");
}
return s;
}
void pd_info_t::init(engine_t *engine, const primitive_desc_t *pd) {
if (is_initialized_) return;
std::call_once(initialization_flag_, [&] {
#define CASE(kind) \
case primitive_kind::kind: \
str_ = init_info_##kind(engine, (const kind##_pd_t *)pd); \
break
switch ((int)pd->kind()) {
CASE(batch_normalization);
CASE(binary);
CASE(concat);
CASE(convolution);
CASE(deconvolution);
CASE(eltwise);
CASE(gated_mlp);
CASE(gemm);
CASE(group_normalization);
CASE(inner_product);
CASE(layer_normalization);
CASE(lrn);
CASE(matmul);
CASE(pooling);
CASE(prelu);
CASE(reduction);
CASE(reorder);
CASE(resampling);
CASE(rnn);
CASE(shuffle);
CASE(softmax);
CASE(sum);
CASE(sdpa);
case primitive_kind::zero_pad:
str_ = "zero_pad, unknown info";
break;
default:
str_ = "unknown primitive info";
assert(!"unknown primitive kind");
}
#undef CASE
is_initialized_ = true;
});
}
} }
dnnl_status_t dnnl_set_verbose(int level) {
using namespace dnnl::impl::status;
using namespace dnnl::impl;
if (level < 0 || level > 2) return invalid_arguments;
uint32_t verbose_level = verbose_t::none;
if (level == 1) verbose_level = verbose_t::level1;
if (level == 2) verbose_level = verbose_t::level2;
if (level == 1 || level == 2) verbose_level |= (level << 24);
verbose.set(verbose_level);
#ifdef DNNL_EXPERIMENTAL_LOGGING
const log_manager_t &log_manager = log_manager_t::get_log_manager();
if (log_manager.is_logger_enabled())
log_manager.set_log_level(std::to_string(level));
#endif
return success;
}
const dnnl_version_t *dnnl_version(void) {
static const dnnl_version_t ver
= {DNNL_VERSION_MAJOR, DNNL_VERSION_MINOR, DNNL_VERSION_PATCH,
DNNL_VERSION_HASH, DNNL_CPU_RUNTIME, DNNL_GPU_RUNTIME};
return &ver;
}