#include <memory>
#include <string>
#include <vector>
#include "oneapi/dnnl/dnnl.hpp"
#include "graph/interface/c_types_map.hpp"
#include "graph/interface/value.hpp"
#include "graph/backend/dnnl/common.hpp"
#include "graph/backend/dnnl/layout_propagator.hpp"
#include "graph/backend/dnnl/op_executable.hpp"
#include "graph/interface/shape_infer.hpp"
namespace dnnl {
namespace impl {
namespace graph {
namespace dnnl_impl {
#define VCHECK_LAYOUT_PROPAGATOR(cond, status, msg, ...) \
VCONDCHECK(graph, create, check, layout_propagator, (cond), status, msg, \
##__VA_ARGS__);
using op_t = op_t;
using op_ptr = std::shared_ptr<op_t>;
using value_ptr = std::shared_ptr<value_t>;
using ltw = logical_tensor_wrapper_t;
status_t insert_reorder_before(op_ptr &op, size_t offset,
const dnnl::memory::desc &opt_mdesc, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
status_t status = status::success;
value_ptr in_val = op->get_input_value(offset);
const logical_tensor_t &in_lt = in_val->get_logical_tensor();
if (make_dnnl_memory_desc(in_lt) == opt_mdesc || ltw(in_lt).is_any())
return status;
auto reorder_op = std::make_shared<op_t>(op_kind::_reorder);
rewriter.insert_op_before(reorder_op, op, offset);
auto scratchpad_val = insert_empty_scratchpad(reorder_op);
auto reorder_out_val = reorder_op->get_output_value(0);
status = fill_layout_info(reorder_out_val, opt_mdesc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder output");
reorder_out_val->set_data_type(ltw(in_lt).data_type());
reorder_out_val->set_dims(ltw(in_lt).vdims());
const auto &pd = reorder_executable_t::create_desc(
reorder_op, p_engine, pd_cache, fpmath, use_block_layout);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t insert_reorder_after(op_ptr &op, size_t offset,
const dnnl::memory::desc &opt_mdesc, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
status_t status = status::success;
value_ptr out_val = op->get_output_value(offset);
const logical_tensor_t &out_lt = out_val->get_logical_tensor();
if (make_dnnl_memory_desc(out_lt) == opt_mdesc || ltw(out_lt).is_any())
return status;
auto reorder_op = std::make_shared<op_t>(op_kind::_reorder);
rewriter.insert_op_after(reorder_op, op, offset);
auto scratchpad_val = insert_empty_scratchpad(reorder_op);
auto reorder_in_val = reorder_op->get_input_value(0);
status = fill_layout_info(reorder_in_val, opt_mdesc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder input");
reorder_in_val->set_data_type(ltw(out_lt).data_type());
reorder_in_val->set_dims(ltw(out_lt).vdims());
const auto &pd = reorder_executable_t::create_desc(
reorder_op, p_engine, pd_cache, fpmath, use_block_layout);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_conv(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = conv_fwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv src");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv weights");
if (op->has_attr(op_attr::with_bias)
&& op->get_attr<bool>(op_attr::with_bias)) {
insert_reorder_before(op, 2, pd.bias_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr bias = op->get_input_value(2);
status = fill_layout_info(bias, pd.bias_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv bias");
}
if (!op->has_attr(op_attr::fusion_info)) {
fusion_info_t fusion_info;
op->set_attr<fusion_info_t>(op_attr::fusion_info, fusion_info);
}
const fusion_info_t &fusion_info
= op->get_attr<fusion_info_t>(op_attr::fusion_info);
if (fusion_info.has_post_dw_conv()) {
const auto &dw_conv = fusion_info.get_post_dw_conv();
auto dw_idx = dw_conv->get_unfused_input_indices();
value_ptr dw_wei = op->get_input_value(dw_idx[0]);
value_ptr dw_bias = nullptr;
if (dw_conv->get_unfused_input_indices().size() > 1) {
dw_bias = op->get_input_value(dw_idx[1]);
}
const auto &dw_wei_opt_mdesc = pd.query_md(query::exec_arg_md,
DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_WEIGHTS);
insert_reorder_before(op, dw_idx[0], dw_wei_opt_mdesc, p_engine,
pd_cache, fpmath, use_block_layout, rewriter);
status = fill_layout_info(dw_wei, dw_wei_opt_mdesc);
if (dw_conv->get_unfused_input_indices().size() > 1) {
const auto &dw_bias_opt_mdesc = pd.query_md(query::exec_arg_md,
DNNL_ARG_ATTR_POST_OP_DW | DNNL_ARG_BIAS);
insert_reorder_before(op, dw_idx[1], dw_bias_opt_mdesc, p_engine,
pd_cache, fpmath, use_block_layout, rewriter);
status = fill_layout_info(dw_bias, dw_bias_opt_mdesc);
}
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before post_dw_conv");
}
if (fusion_info.has_post_binary()) {
const auto &post_ops = fusion_info.get_post_ops();
for (size_t i = 0; i < post_ops.size(); ++i) {
if (!post_ops[i]->is_post_binary()) continue;
const auto &binary = post_ops[i];
std::vector<size_t> binary_idx
= binary->get_unfused_input_indices();
if (binary_idx.empty()) continue;
value_ptr binary_unfused_src = op->get_input_value(binary_idx[0]);
const auto &binary_unfused_src_opt_mdesc
= pd.query_md(query::exec_arg_md,
DNNL_ARG_SRC_1
| DNNL_ARG_ATTR_MULTIPLE_POST_OP(
static_cast<int>(i)));
insert_reorder_before(op, binary_idx[0],
binary_unfused_src_opt_mdesc, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
status = fill_layout_info(
binary_unfused_src, binary_unfused_src_opt_mdesc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before "
"conv post_binary");
}
}
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after conv dst");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_deconv(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = deconv_fwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv src");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv weights");
if (op->has_attr(op_attr::with_bias)
&& op->get_attr<bool>(op_attr::with_bias)) {
insert_reorder_before(op, 2, pd.bias_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr bias = op->get_input_value(2);
status = fill_layout_info(bias, pd.bias_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv bias");
}
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after deconv dst");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_deconv_bwd_data(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = deconv_bwd_data_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(0);
status_t status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv_bwd_data "
"diff_dst");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv_bwd_data "
"weights");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after deconv_bwd_data "
"diff_src");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_deconv_bwd_weights(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = deconv_bwd_weights_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv_bwd_weights "
"src");
insert_reorder_before(op, 1, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(1);
status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before deconv_bwd_weights "
"diff_dst");
insert_reorder_after(op, 0, pd.diff_weights_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr diff_weights = op->get_output_value(0);
status = fill_layout_info(diff_weights, pd.diff_weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after deconv_bwd_weights "
"diff_weights");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_eltwise(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = eltwise_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after eltwise dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_eltwise_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = eltwise_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
auto opt_desc = (op->has_attr(op_attr::use_dst)
&& op->get_attr<bool>(op_attr::use_dst))
? pd.dst_desc()
: pd.src_desc();
insert_reorder_before(op, 0, opt_desc, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr data = op->get_input_value(0);
status_t status = fill_layout_info(data, opt_desc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before eltwise_bwd "
"inputs 0");
insert_reorder_before(op, 1, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(1);
status = fill_layout_info(diff_dst, opt_desc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before eltwise_bwd "
"diff_dst");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after eltwise_bwd "
"diff_src");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_binary(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
using ltw = logical_tensor_wrapper_t;
status_t status = status::success;
if (ltw(op->get_input_logical_tensor(0)).has_zero_dim()
|| ltw(op->get_input_logical_tensor(1)).has_zero_dim()) {
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst,
to_ncx_format(
make_dnnl_memory_desc(dst->get_logical_tensor())));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for binary logical tensor with 0 "
"dims");
return fill_layout_info(op->get_output_value(1), dnnl::memory::desc {});
}
const auto &pd = binary_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after binary dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_concat(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
status_t status = status::success;
const auto &pd = concat_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
for (size_t i = 0; i < op->num_inputs(); ++i) {
insert_reorder_before(op, i, pd.src_desc(static_cast<int>(i)), p_engine,
pd_cache, fpmath, use_block_layout, rewriter);
status = fill_layout_info(
op->get_input_value(i), pd.src_desc(static_cast<int>(i)));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before concat "
"src");
}
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
status = fill_layout_info(op->get_output_value(0), pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after concat dst");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_shuffle(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = shuffle_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
value_ptr src = op->get_input_value(0);
value_ptr dst = op->get_output_value(0);
VCHECK_LAYOUT_PROPAGATOR(!ltw(src->get_logical_tensor()).is_any(),
status::invalid_arguments, "shuffle's src layout can't be any");
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after shuffle dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_matmul(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
using ltw = logical_tensor_wrapper_t;
status_t status = status::success;
if (ltw(op->get_input_logical_tensor(0)).has_zero_dim()
|| ltw(op->get_input_logical_tensor(1)).has_zero_dim()) {
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst,
to_ncx_format(
make_dnnl_memory_desc(dst->get_logical_tensor())));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for matmul 0 dims dst");
return fill_layout_info(op->get_output_value(1), dnnl::memory::desc {});
}
const auto &pd = matmul_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before matmul src 0");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before matmul src 1");
if (op->has_attr(op_attr::with_bias)
&& op->get_attr<bool>(op_attr::with_bias)) {
insert_reorder_before(op, 2, pd.bias_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr bias = op->get_input_value(2);
status = fill_layout_info(bias, pd.bias_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before matmul bias");
}
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after matmul dst");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_pool(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = pool_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after pool dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after pool scratchpad");
if (op->has_attr(op_attr::is_training)
&& op->get_attr<bool>(op_attr::is_training)) {
value_ptr workspace_val = op->get_output_value(2);
const memory::desc &ws_md = pd.workspace_desc();
workspace_val->set_dims(ws_md.get_dims());
workspace_val->set_data_type(
static_cast<data_type_t>(ws_md.get_data_type()));
status = fill_layout_info(workspace_val, ws_md);
}
return status;
}
status_t layout_propagator_for_pool_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = pool_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(0);
status_t status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before pool_bwd "
"diff_dst");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after pool_bwd diff_src");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_batchnorm(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = batchnorm_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before batchnorm src");
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after batchnorm dst");
if (op->get_attr<bool>(op_attr::is_training)) {
value_ptr running_mean = op->get_output_value(1);
value_ptr running_variance = op->get_output_value(2);
value_ptr batch_mean = op->get_output_value(3);
value_ptr batch_variance = op->get_output_value(4);
status = fill_layout_info(running_mean, pd.mean_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm running_mean");
status = fill_layout_info(running_variance, pd.variance_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm running_variance");
status = fill_layout_info(batch_mean, pd.mean_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm batch_mean");
status = fill_layout_info(batch_variance, pd.variance_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm batch_variance");
}
size_t scratchpad_index = op->num_outputs() - 1;
if (op->has_attr(op_attr::fuse_relu)
&& op->get_attr<bool>(op_attr::fuse_relu)) {
scratchpad_index = op->num_outputs() - 2;
value_ptr workspace_val = op->get_output_value(op->num_outputs() - 1);
status = fill_layout_info(workspace_val, pd.workspace_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm workspace");
}
value_ptr scratchpad_val = op->get_output_value(scratchpad_index);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_batchnorm_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = batchnorm_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before batchnorm_bwd "
"src");
insert_reorder_before(op, 1, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(1);
status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before batchnorm_bwd "
"diff_dst");
insert_reorder_before(op, 2, pd.mean_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr mean = op->get_input_value(2);
status = fill_layout_info(mean, pd.mean_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before batchnorm_bwd "
"mean");
insert_reorder_before(op, 3, pd.variance_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr var = op->get_input_value(3);
status = fill_layout_info(var, pd.variance_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before batchnorm_bwd "
"virance");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after batchnorm_bwd "
"diff_src");
if (op->num_outputs() > 2) {
value_ptr diff_gamma = op->get_output_value(1);
value_ptr diff_beta = op->get_output_value(2);
status = fill_layout_info(diff_gamma, pd.diff_weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm_bwd diff_gamma");
status = fill_layout_info(diff_beta, pd.diff_weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for batchnorm_bwd diff_beta");
}
value_ptr scratchpad_val = op->get_output_values().back();
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_prelu(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = prelu_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before prelu src");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before prelu weights");
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after prelu dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_prelu_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = prelu_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before prelu_bwd src");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before prelu_bwd "
"weights");
value_ptr diff_dst = op->get_input_value(2);
status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for prelu_bwd diff_dst");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after prelu_bwd "
"diff_src");
insert_reorder_after(op, 1, pd.diff_weights_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr diff_wei = op->get_output_value(1);
status = fill_layout_info(diff_wei, pd.diff_weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after prelu_bwd "
"diff_weights");
value_ptr scratchpad_val = op->get_output_value(2);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_layernorm(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = layernorm_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before layernorm src");
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after layernorm dst");
if (op->num_outputs() > 2) {
value_ptr mean = op->get_output_value(1);
value_ptr variance = op->get_output_value(2);
status = fill_layout_info(mean, pd.mean_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for layernorm mean");
status = fill_layout_info(variance, pd.variance_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for layernorm variance");
}
value_ptr scratchpad_val = op->get_output_values().back();
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_layernorm_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = layernorm_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
size_t in_index {0};
insert_reorder_before(op, in_index, pd.src_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr src = op->get_input_value(in_index++);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before layernorm_bwd "
"src");
insert_reorder_before(op, in_index, pd.diff_dst_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(in_index++);
status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before layernorm_bwd "
"diff_dst");
insert_reorder_before(op, in_index, pd.mean_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr mean = op->get_input_value(in_index++);
status = fill_layout_info(mean, pd.mean_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before layernorm_bwd "
"mean");
insert_reorder_before(op, in_index, pd.variance_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr var = op->get_input_value(in_index++);
status = fill_layout_info(var, pd.variance_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before layernorm_bwd "
"variance");
size_t out_index {0};
insert_reorder_after(op, out_index, pd.diff_src_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(out_index++);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after layernorm_bwd "
"diff_src");
const bool use_affine = op->get_attr<bool>(op_attr::use_affine);
if (use_affine) {
const auto &diff_scale_opt_mdesc
= pd.query_md(query::exec_arg_md, DNNL_ARG_DIFF_SCALE);
insert_reorder_after(op, out_index, diff_scale_opt_mdesc, p_engine,
pd_cache, fpmath, use_block_layout, rewriter);
value_ptr diff_scale = op->get_output_value(out_index++);
status = fill_layout_info(diff_scale, diff_scale_opt_mdesc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after layernorm_bwd "
"diff_scale");
const auto &diff_shift_opt_mdesc
= pd.query_md(query::exec_arg_md, DNNL_ARG_DIFF_SHIFT);
insert_reorder_after(op, out_index, diff_shift_opt_mdesc, p_engine,
pd_cache, fpmath, use_block_layout, rewriter);
value_ptr diff_shift = op->get_output_value(out_index++);
status = fill_layout_info(diff_shift, diff_shift_opt_mdesc);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after layernorm_bwd "
"diff_shift");
}
auto scratchpad_val = op->get_output_value(op->num_outputs() - 1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_permute(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
status_t status = status::success;
std::shared_ptr<value_t> src, dst;
src = op->get_input_value(0);
dst = op->get_output_value(0);
auto in_lt = src->get_logical_tensor();
auto out_lt = dst->get_logical_tensor();
auto perm = op->get_attr<std::vector<int64_t>>(op_attr::permutation);
if (!ltw(in_lt).is_any() && ltw(out_lt).is_any()) {
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
auto int32_perm = dnnl_impl::utils::cast_to_int32(perm);
dnnl::memory::desc out_md = in_md.permute_axes(int32_perm);
status = fill_layout_info(dst, out_md);
} else if (!ltw(out_lt).is_any() && ltw(in_lt).is_any()) {
dnnl::memory::desc out_md = make_dnnl_memory_desc(out_lt);
std::vector<int32_t> inverse_perm(perm.size(), -1);
for (size_t i = 0; i < perm.size(); i++) {
inverse_perm[static_cast<size_t>(perm[i])]
= static_cast<int32_t>(i);
}
dnnl::memory::desc in_md = out_md.permute_axes(inverse_perm);
status = fill_layout_info(src, in_md);
} else if (!ltw(in_lt).is_any() && !ltw(out_lt).is_any()) {
dnnl::memory::desc out_md = make_dnnl_memory_desc(out_lt);
std::vector<int32_t> inverse_perm(perm.size(), -1);
for (size_t i = 0; i < perm.size(); i++) {
inverse_perm[static_cast<size_t>(perm[i])]
= static_cast<int32_t>(i);
}
dnnl::memory::desc tmp_in_md = out_md.permute_axes(inverse_perm);
if (make_dnnl_memory_desc(in_lt) != tmp_in_md)
insert_reorder_before(op, 0, tmp_in_md, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
}
return status;
}
status_t layout_propagator_for_to_group(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
status_t status = status::success;
std::shared_ptr<value_t> src, dst;
src = op->get_input_value(0);
dst = op->get_output_value(0);
auto in_lt = src->get_logical_tensor();
auto out_lt = dst->get_logical_tensor();
if (!ltw(in_lt).is_any() && ltw(out_lt).is_any()) {
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
dnnl::memory::desc out_md;
auto groups = op->get_attr<int64_t>(op_attr::groups);
if (groups == 0) return status::invalid_shape;
if (op->has_attr(op_attr::is_convtranspose)
&& op->get_attr<bool>(op_attr::is_convtranspose)) {
auto permuted_weight = transpose(in_md, 0, 1);
auto permuted_group_weight = to_grouped(permuted_weight, groups);
out_md = transpose(permuted_group_weight, 1, 2);
} else {
out_md = to_grouped(in_md, groups);
}
status = fill_layout_info(dst, out_md);
}
return status;
}
status_t layout_propagator_for_from_group(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
status_t status = status::success;
const auto get_dst_md
= [](const dnnl::memory::desc &src_md,
bool is_convtranspose) -> dnnl::memory::desc {
if (is_convtranspose) {
auto permuted_dst = transpose(src_md, 1, 2);
auto permuted_dst_no_groups = from_grouped(permuted_dst);
return !permuted_dst_no_groups
? permuted_dst_no_groups
: transpose(permuted_dst_no_groups, 0, 1);
} else {
return from_grouped(src_md);
}
};
const auto get_strides = [](const dnnl::memory::desc &src_md,
bool is_convtranspose) -> dims {
if (is_convtranspose) {
auto strides
= get_dense_strides(transpose(src_md, 0, 1).get_dims());
std::swap(strides[0], strides[1]);
return strides;
} else {
return get_dense_strides(src_md.get_dims());
}
};
value_ptr src = op->get_input_value(0);
value_ptr dst = op->get_output_value(0);
auto src_lt = src->get_logical_tensor();
auto dst_lt = dst->get_logical_tensor();
if (ltw(src_lt).is_any()) return status;
const bool is_convtranspose = op->has_attr(op_attr::is_convtranspose)
? op->get_attr<bool>(op_attr::is_convtranspose)
: false;
const auto src_md = make_dnnl_memory_desc(src_lt);
dnnl::memory::desc inferred_dst_md = get_dst_md(src_md, is_convtranspose);
if (!inferred_dst_md) {
dnnl::memory::desc strided_dst_md(src_md.get_dims(),
src_md.get_data_type(), get_strides(src_md, is_convtranspose));
insert_reorder_before(op, 0, strided_dst_md, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
inferred_dst_md = get_dst_md(strided_dst_md, is_convtranspose);
}
if (ltw(dst_lt).is_any()) {
status = fill_layout_info(dst, inferred_dst_md);
} else {
insert_reorder_after(op, 0, inferred_dst_md, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
}
return status;
}
static status_t layout_propagator_for_reshape_like_ops(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter, const dnnl::memory::dims &target_dims) {
status_t status = status::success;
std::shared_ptr<value_t> src, dst;
src = op->get_input_value(0);
dst = op->get_output_value(0);
auto in_lt = src->get_logical_tensor();
auto out_lt = dst->get_logical_tensor();
VCHECK_LAYOUT_PROPAGATOR(!ltw(in_lt).is_any(), status::invalid_arguments,
"input layout must be specified for reshape_like");
if (target_dims.empty()) {
dst->set_strides({});
return status::success;
}
if (ltw(out_lt).is_any()) {
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
dnnl::memory::desc out_md
= in_md.reshape(target_dims, true);
if (!out_md) {
dnnl::memory::desc reshapable_md(in_md.get_dims(),
in_md.get_data_type(), get_ncx_format(in_md.get_ndims()));
insert_reorder_before(op, 0, reshapable_md, p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
out_md = reshapable_md.reshape(target_dims);
}
status = fill_layout_info(dst, out_md);
} else if (ltw(out_lt).is_strided()) {
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
dnnl::memory::desc out_md = make_dnnl_memory_desc(out_lt);
dnnl::memory::desc expected_in_md
= out_md.reshape(in_md.get_dims(), true);
if (expected_in_md) {
if (expected_in_md != in_md) {
insert_reorder_before(op, 0, expected_in_md, p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
}
} else {
dnnl::memory::desc reshaped_in_md
= in_md.reshape(target_dims, true);
if (!reshaped_in_md) {
dnnl::memory::desc reshapable_md(in_md.get_dims(),
in_md.get_data_type(),
get_ncx_format(in_md.get_ndims()));
insert_reorder_before(op, 0, reshapable_md, p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
reshaped_in_md = reshapable_md.reshape(target_dims);
}
if (reshaped_in_md != out_md) {
insert_reorder_after(op, 0, reshaped_in_md, p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
}
}
}
return status;
}
status_t layout_propagator_for_reshape(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
auto out_lt = op->get_output_value(0)->get_logical_tensor();
auto target_dims = ltw(out_lt).vdims();
status_t status = layout_propagator_for_reshape_like_ops(op, p_engine,
pd_cache, fpmath, use_block_layout, rewriter, target_dims);
return status;
}
status_t layout_propagator_for_transpose(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
status_t status = status::success;
std::shared_ptr<value_t> src, dst;
src = op->get_input_value(0);
dst = op->get_output_value(0);
auto in_lt = src->get_logical_tensor();
auto out_lt = dst->get_logical_tensor();
VCHECK_LAYOUT_PROPAGATOR(!ltw(in_lt).is_any(), status::invalid_arguments,
"layout of transpose src can't be any layout");
std::vector<int64_t> order
= op->get_attr<std::vector<int64_t>>(op_attr::order);
if (!order.empty()) {
for (int64_t &axis : order) {
if (axis < 0) axis += ltw(in_lt).ndims();
}
} else {
VCHECK_LAYOUT_PROPAGATOR(false, status::unimplemented,
"transpose with empty order is not supported");
}
std::vector<int> axes(order.size(), -1);
for (size_t i = 0; i < order.size(); i++) {
size_t new_shape_idx = i;
size_t org_shape_idx = order[i];
axes[org_shape_idx] = static_cast<int>(new_shape_idx);
}
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
dnnl::memory::desc expected_out_md = in_md.permute_axes(axes);
if (ltw(out_lt).is_any()) {
status = fill_layout_info(dst, expected_out_md);
} else {
dnnl::memory::desc out_md = make_dnnl_memory_desc(out_lt);
if (expected_out_md != out_md) {
insert_reorder_after(op, 0, expected_out_md, p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
}
}
return status;
}
status_t layout_propagator_for_unsqueeze(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(rewriter);
status_t status = status::success;
value_ptr src = op->get_input_value(0);
value_ptr dst = op->get_output_value(0);
auto in_lt = src->get_logical_tensor();
auto out_lt = dst->get_logical_tensor();
if (!ltw(in_lt).is_any() && ltw(out_lt).is_any()) {
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
status = fill_layout_info(dst, in_md.reshape(ltw(out_lt).vdims()));
}
return status;
}
status_t layout_propagator_for_squeeze(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
auto out_lt = op->get_output_value(0)->get_logical_tensor();
auto target_dims = ltw(out_lt).vdims();
status_t status = layout_propagator_for_reshape_like_ops(op, p_engine,
pd_cache, fpmath, use_block_layout, rewriter, target_dims);
return status;
}
status_t layout_propagator_for_reorder(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(rewriter);
status_t status = status::success;
std::shared_ptr<value_t> src, dst;
src = op->get_input_value(0);
dst = op->get_output_value(0);
auto in_lt = src->get_logical_tensor();
auto out_lt = dst->get_logical_tensor();
if (!ltw(in_lt).is_any() && ltw(out_lt).is_any()) {
VCHECK_LAYOUT_PROPAGATOR(!op->has_attr(op_attr::change_layout)
|| !op->get_attr<bool>(op_attr::change_layout),
status::invalid_arguments,
"layout of dnnl_reorder input and output must be known "
"if it changes layout");
auto out_md = make_dnnl_memory_desc(in_lt);
if (in_lt.data_type != out_lt.data_type) {
auto format_tag = md2fmt_tag_str(out_md.get());
const auto &dims = out_md.get_dims();
dnnl_memory_desc_t tmp_md;
dnnl_memory_desc_create_with_string_tag(&tmp_md,
static_cast<int>(dims.size()), dims.data(),
static_cast<dnnl_data_type_t>(out_lt.data_type),
format_tag.data());
status = fill_layout_info(dst, tmp_md);
} else {
status = fill_layout_info(dst, out_md);
}
} else if (!ltw(out_lt).is_any() && ltw(in_lt).is_any()) {
VCHECK_LAYOUT_PROPAGATOR(!op->has_attr(op_attr::change_layout)
|| !op->get_attr<bool>(op_attr::change_layout),
status::invalid_arguments,
"layout of dnnl_reorder input and output must be known "
"if it changes layout");
out_lt.data_type = ltw(in_lt).data_type();
auto in_md = make_dnnl_memory_desc(out_lt);
status = fill_layout_info(src, in_md);
}
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder");
if (op->num_outputs() == 1) { insert_empty_scratchpad(op); }
const auto &pd = reorder_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_mul_scales(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
return layout_propagator_for_reorder(
op, p_engine, pd_cache, fpmath, use_block_layout, rewriter);
}
status_t layout_propagator_for_bn_folding(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(rewriter);
status_t status = status::success;
for (size_t i = 0; i < op->num_outputs() - 1; i++) {
auto in_lt = op->get_input_logical_tensor(i);
auto out_lt = op->get_output_logical_tensor(i);
if (!ltw(in_lt).is_any() && ltw(out_lt).is_any()) {
dnnl::memory::desc in_md = make_dnnl_memory_desc(in_lt);
auto dst = op->get_output_value(i);
status = fill_layout_info(dst, in_md);
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for bn_folding dst");
}
}
auto pd = bn_folding_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
auto val = op->get_output_value(2);
status = fill_layout_info(val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_conv_bwd_data(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = conv_bwd_data_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(0);
status_t status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv_bwd_data "
"diff_dst");
insert_reorder_before(op, 1, pd.weights_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr wei = op->get_input_value(1);
status = fill_layout_info(wei, pd.weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv_bwd_data "
"weights");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after conv_bwd_data "
"diff_src");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_conv_bwd_weights(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = conv_bwd_weights_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr src = op->get_input_value(0);
status_t status = fill_layout_info(src, pd.src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv_bwd_weights "
"src");
insert_reorder_before(op, 1, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(1);
status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before conv_bwd_weights "
"diff_dst");
insert_reorder_after(op, 0, pd.diff_weights_desc(), p_engine, pd_cache,
fpmath, use_block_layout, rewriter);
value_ptr diff_weights = op->get_output_value(0);
status = fill_layout_info(diff_weights, pd.diff_weights_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after conv_bwd_weights "
"diff_weights");
auto scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc = pd.scratchpad_desc();
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
status_t layout_propagator_for_resampling(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = resampling_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after interpolate "
"dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_resampling_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = resampling_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status_t status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after interpolate_bwd "
"diff_src");
auto scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_sum(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
value_ptr dst = op->get_output_value(0);
bool input_has_any_format = false;
for (const auto &in_val : op->get_input_values()) {
if (ltw(in_val->get_logical_tensor()).is_any()) {
input_has_any_format = true;
break;
}
}
MAYBE_UNUSED(input_has_any_format);
assertm(!input_has_any_format,
"input format of sum primitive cannot be any");
VCHECK_LAYOUT_PROPAGATOR(!input_has_any_format, status::invalid_arguments,
"input format of sum primitive cannot be any ");
const auto &pd = sum_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
if (ltw(dst->get_logical_tensor()).is_any()) {
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after sum dst");
}
value_ptr scratchpad_val = op->get_output_values().back();
status_t status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_softmax(op_ptr &op, const dnnl::engine &p_engine,
pd_cache_t &pd_cache, const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
value_ptr src = op->get_input_value(0);
VCHECK_LAYOUT_PROPAGATOR(!ltw(src->get_logical_tensor()).is_any(),
status::invalid_arguments,
"layout of softmax/logsoftmax src can't be any");
const auto &pd = softmax_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after softmax dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_softmax_bwd(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
value_ptr dst = op->get_input_value(1);
VCHECK_LAYOUT_PROPAGATOR(!ltw(dst->get_logical_tensor()).is_any(),
status::invalid_arguments,
"layout of softmax/logsoftmax bwd dst can't be any");
const auto &pd = softmax_bwd_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_before(op, 0, pd.diff_dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_dst = op->get_input_value(0);
status_t status = fill_layout_info(diff_dst, pd.diff_dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder before softmax_bwd "
"diff_dst");
insert_reorder_after(op, 0, pd.diff_src_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr diff_src = op->get_output_value(0);
status = fill_layout_info(diff_src, pd.diff_src_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after softmax_bwd "
"diff_src");
auto scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_reduction(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
value_ptr src = op->get_input_value(0);
VCHECK_LAYOUT_PROPAGATOR(!ltw(src->get_logical_tensor()).is_any(),
status::invalid_arguments, "layout of reduction src can't be any");
const auto &pd = reduction_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after reduction dst");
value_ptr scratchpad_val = op->get_output_value(1);
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_constant_filler(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(op);
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
return status::success;
}
status_t layout_propagator_for_sub_zps(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(op);
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
assertm(false,
"dnnl_sub_zps op is only for fusion purpose, we shouldn't do "
"layout propagation for it");
return status::invalid_graph_op;
}
status_t layout_propagator_for_add_zps(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(op);
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
assertm(false,
"dnnl_add_zps op is only for fusion purpose, we shouldn't do "
"layout propagation for it");
return status::invalid_graph_op;
}
status_t layout_propagator_for_gen_index(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
auto src_md = make_dnnl_memory_desc(op->get_input_logical_tensor(0));
if (!is_plain(src_md)) {
src_md = dnnl::memory::desc(src_md.get_dims(), src_md.get_data_type(),
dnnl::memory::format_tag::abcd);
insert_reorder_before(op, 0, src_md, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
}
value_ptr dst_val = op->get_output_value(0);
status_t status = fill_layout_info(dst_val, src_md);
return status;
}
status_t layout_propagator_for_identity(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
logical_tensor_t dst_lt = op->get_input_logical_tensor(0);
VCHECK_LAYOUT_PROPAGATOR(!ltw(dst_lt).is_any(), status::invalid_arguments,
"layout of identity dst can't be any");
auto dst_md = make_dnnl_memory_desc(dst_lt);
auto src_md = make_dnnl_memory_desc(op->get_input_logical_tensor(0));
if (src_md != dst_md) {
insert_reorder_before(op, 0, dst_md, p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
}
return status::success;
}
status_t layout_propagator_for_groupnorm(op_ptr &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
const auto &pd = groupnorm_executable_t::create_desc(
op, p_engine, pd_cache, fpmath, use_block_layout);
insert_reorder_after(op, 0, pd.dst_desc(), p_engine, pd_cache, fpmath,
use_block_layout, rewriter);
value_ptr dst = op->get_output_value(0);
status_t status = fill_layout_info(dst, pd.dst_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for reorder after groupnorm dst");
if (op->num_outputs() > 2) {
value_ptr mean = op->get_output_value(1);
value_ptr variance = op->get_output_value(2);
status = fill_layout_info(mean, pd.mean_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for groupnorm mean");
status = fill_layout_info(variance, pd.variance_desc());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for groupnorm variance");
}
value_ptr scratchpad_val = op->get_output_values().back();
status = fill_layout_info(scratchpad_val, pd.scratchpad_desc());
return status;
}
status_t layout_propagator_for_mask(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
auto src_md = make_dnnl_memory_desc(op->get_input_logical_tensor(0));
value_ptr dst_val = op->get_output_value(0);
status_t status = fill_layout_info(dst_val, src_md);
return status;
}
status_t layout_propagator_for_sdpa(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
size_t output_idx = 0;
value_ptr dst_val = op->get_output_value(output_idx++);
const logical_tensor_t &out_lt = dst_val->get_logical_tensor();
dnnl::memory::desc expected_md;
if (ltw(out_lt).is_any()) {
if (!dst_val->get_consumers().empty()) {
const auto &consumer_op = dst_val->get_consumers()[0].get_op();
const logical_tensor_t &consumer_out
= consumer_op.get_output_logical_tensor(0);
if (consumer_op.get_kind() == op_kind::_reshape
&& ltw(consumer_out).ndims() == 5
&& ltw(consumer_out).is_strided()) {
const auto &ori_strides = ltw(consumer_out).vstrides();
std::vector<dim_t> strides = {ori_strides[0], ori_strides[2],
ori_strides[3], ori_strides[4]};
expected_md = {ltw(out_lt).vdims(),
static_cast<dnnl::memory::data_type>(
ltw(out_lt).data_type()),
strides};
} else {
expected_md = {ltw(out_lt).vdims(),
static_cast<dnnl::memory::data_type>(
ltw(out_lt).data_type()),
dnnl::memory::format_tag::acbd};
}
} else {
expected_md = {ltw(out_lt).vdims(),
static_cast<dnnl::memory::data_type>(
ltw(out_lt).data_type()),
dnnl::memory::format_tag::acbd};
}
} else {
expected_md = make_dnnl_memory_desc(out_lt);
}
status_t status = fill_layout_info(dst_val, expected_md);
value_ptr scratchpad_val = op->get_output_value(output_idx++);
const memory::desc scratchpad_desc;
status = fill_layout_info(scratchpad_val, scratchpad_desc);
if (op->get_attr<bool>(op_attr::is_training)) {
value_ptr stats_val = op->get_output_value(output_idx);
const logical_tensor_t &stats_lt = stats_val->get_logical_tensor();
dnnl::memory::desc stats_md;
if (!stats_val->get_consumers().empty()) {
const auto &consumer_op = stats_val->get_consumers()[0].get_op();
const logical_tensor_t &consumer_out
= consumer_op.get_output_logical_tensor(0);
if (consumer_op.get_kind() == op_kind::_reshape
&& ltw(consumer_out).ndims() == 5
&& ltw(consumer_out).is_strided()) {
const auto &ori_strides = ltw(consumer_out).vstrides();
std::vector<dim_t> strides = {ori_strides[0], ori_strides[2],
ori_strides[3], ori_strides[4]};
stats_md = {ltw(stats_lt).vdims(),
static_cast<dnnl::memory::data_type>(
ltw(stats_lt).data_type()),
strides};
} else {
stats_md = {ltw(stats_lt).vdims(),
static_cast<dnnl::memory::data_type>(
ltw(out_lt).data_type()),
dnnl::memory::format_tag::acbd};
}
} else {
expected_md = {ltw(out_lt).vdims(),
static_cast<dnnl::memory::data_type>(
ltw(out_lt).data_type()),
dnnl::memory::format_tag::acbd};
}
status = fill_layout_info(stats_val, stats_md);
}
return status;
}
status_t layout_propagator_for_sdpa_bwd(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(pd_cache);
UNUSED(use_block_layout);
UNUSED(rewriter);
auto get_md_for_diff = [](const logical_tensor_t <) {
if (!ltw(lt).is_any()) return make_dnnl_memory_desc(lt);
return dnnl::memory::desc {ltw(lt).vdims(),
static_cast<dnnl::memory::data_type>(ltw(lt).data_type()),
dnnl::memory::format_tag::acbd};
};
status_t status = status::success;
size_t output_idx = 0;
value_ptr diff_query_val = op->get_output_value(output_idx++);
const logical_tensor_t &query_lt = op->get_input_logical_tensor(0);
status = fill_layout_info(diff_query_val, get_md_for_diff(query_lt));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for sdpa_bwd diff_query");
value_ptr diff_key_val = op->get_output_value(output_idx++);
const logical_tensor_t &key_lt = op->get_input_logical_tensor(1);
status = fill_layout_info(diff_key_val, get_md_for_diff(key_lt));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for sdpa_bwd diff_key");
value_ptr diff_value_val = op->get_output_value(output_idx++);
const logical_tensor_t &value_lt = op->get_input_logical_tensor(2);
status = fill_layout_info(diff_value_val, get_md_for_diff(value_lt));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for sdpa_bwd diff_value");
{
const bool with_scale = op->get_attr<bool>(op_attr::with_scale);
const auto mask_type = static_cast<attn_mask_type_t>(
op->get_attr<int64_t>(op_attr::mask_type));
const bool is_invert_scale = op->has_attr(op_attr::is_invert_scale)
? op->get_attr<bool>(op_attr::is_invert_scale)
: false;
const bool with_explicit_mask = mask_type == attn_mask_type::buffer;
auto md_q = make_dnnl_memory_desc(op->get_input_logical_tensor(0));
auto md_k = make_dnnl_memory_desc(op->get_input_logical_tensor(1));
auto md_v = make_dnnl_memory_desc(op->get_input_logical_tensor(2));
auto md_dst = make_dnnl_memory_desc(op->get_input_logical_tensor(3));
auto md_diff_dst
= make_dnnl_memory_desc(op->get_input_logical_tensor(5));
auto md_diff_q = get_md_for_diff(op->get_input_logical_tensor(0));
auto md_diff_k = get_md_for_diff(op->get_input_logical_tensor(1));
auto md_diff_v = get_md_for_diff(op->get_input_logical_tensor(2));
dnnl::memory::desc md_scale, md_attn_mask, md_dS;
size_t idx = 6;
if (with_scale)
md_scale = make_dnnl_memory_desc(
op->get_input_logical_tensor(idx++));
if (with_explicit_mask) {
md_attn_mask = make_dnnl_memory_desc(
op->get_input_logical_tensor(idx++));
if (op->num_outputs() > 4)
md_dS = make_dnnl_memory_desc(op->get_output_logical_tensor(4));
}
const auto &sdpa_fusion_info = op->has_attr(op_attr::fusion_info)
? op->get_attr<fusion_info_t>(op_attr::fusion_info)
: fusion_info_t();
dnnl::primitive_attr attr, qk_attr, vs_attr;
if (op->has_attr(op_attr::fusion_info)) {
qk_attr = make_dnnl_sdpa_primitive_attr(
op, sdpa_fusion_info, attr_type_t::QK);
vs_attr = make_dnnl_sdpa_primitive_attr(
op, sdpa_fusion_info, attr_type_t::VS);
}
qk_attr.set_accumulation_mode(str2accumulation_mode(
op->get_attr<std::string>(op_attr::qk_acc_mode)));
vs_attr.set_accumulation_mode(str2accumulation_mode(
op->get_attr<std::string>(op_attr::vs_acc_mode)));
attr.set_scratchpad_mode(dnnl::scratchpad_mode::user);
attr.set_fpmath_mode(static_cast<dnnl::fpmath_mode>(fpmath.mode_));
dim_t kv_head_number = op->get_input_logical_tensor(1).dims[1];
const alg_kind_t softmax_alg = alg_kind::softmax_accurate_inf_as_zero;
std::shared_ptr<primitive_desc_t> hint_fwd_pd;
status = create_sdpa_pd(hint_fwd_pd, p_engine.get(), md_q.get(),
md_k.get(), md_v.get(), md_dst.get(), md_attn_mask.get(),
md_scale.get(), is_invert_scale, kv_head_number, mask_type,
softmax_alg, impl::prop_kind::forward_training, attr.get(),
qk_attr.get(), vs_attr.get());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to create hint fwd pd for sdpa_bwd scratchpad");
std::shared_ptr<primitive_desc_t> sdpa_bwd_pd;
status = create_sdpa_pd(sdpa_bwd_pd, p_engine.get(), md_q.get(),
md_k.get(), md_v.get(), md_dst.get(), md_diff_q.get(),
md_diff_k.get(), md_diff_v.get(), md_diff_dst.get(),
md_dS.get(), md_attn_mask.get(), md_scale.get(),
is_invert_scale, kv_head_number, mask_type, softmax_alg,
attr.get(), hint_fwd_pd.get(), qk_attr.get(), vs_attr.get());
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to create pd for sdpa_bwd scratchpad");
value_ptr scratchpad_val = op->get_output_value(output_idx++);
dnnl_memory_desc_t cloned_md = nullptr;
dnnl_memory_desc_clone(&cloned_md, sdpa_bwd_pd->scratchpad_md());
dnnl::memory::desc scratchpad_desc;
scratchpad_desc.reset(cloned_md);
status = fill_layout_info(scratchpad_val, scratchpad_desc);
}
if (op->num_outputs() > output_idx) {
value_ptr diff_mask_val = op->get_output_value(output_idx);
const logical_tensor_t &diff_mask_lt
= diff_mask_val->get_logical_tensor();
status = fill_layout_info(
diff_mask_val, make_dnnl_memory_desc(diff_mask_lt));
VCHECK_LAYOUT_PROPAGATOR(status == status::success, status,
"failed to fill layout info for sdpa_bwd diff_mask");
}
return status;
}
status_t layout_propagator_for_host_scalar(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(op);
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
return status::success;
}
status_t layout_propagator_for_gated_mlp(std::shared_ptr<op_t> &op,
const dnnl::engine &p_engine, pd_cache_t &pd_cache,
const fpmath_t &fpmath, bool use_block_layout,
subgraph_rewriter_t &rewriter) {
UNUSED(p_engine);
UNUSED(pd_cache);
UNUSED(fpmath);
UNUSED(use_block_layout);
UNUSED(rewriter);
value_ptr dst_val = op->get_output_value(0);
const logical_tensor_t &dst_lt = dst_val->get_logical_tensor();
dnnl::memory::desc expected_md;
if (ltw(dst_lt).is_any()) {
const auto tag = get_ncx_format(ltw(dst_lt).ndims());
expected_md = {ltw(dst_lt).vdims(),
static_cast<dnnl::memory::data_type>(ltw(dst_lt).data_type()),
tag};
} else {
expected_md = make_dnnl_memory_desc(dst_lt);
}
status_t status = fill_layout_info(dst_val, expected_md);
value_ptr scratchpad_val = op->get_output_value(1);
const memory::desc scratchpad_desc;
status = fill_layout_info(scratchpad_val, scratchpad_desc);
return status;
}
} } } }