#include "gpu/intel/conv/ref.hpp"
#include "gpu/intel/primitive_conf.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
namespace intel {
namespace conv {
static status_t init_conf_common(
conf_t &conf, const pd_t *pd, impl::engine_t *engine) {
const desc_t &cd = *pd->desc();
const memory_desc_t &src_md = *pd->invariant_src_md();
const memory_desc_t &weights_md = *pd->invariant_wei_md();
const memory_desc_t &dst_md = *pd->invariant_dst_md();
const memory_desc_t &bias_md = *pd->invariant_bia_md();
const primitive_attr_t &attr = *pd->attr();
set_default_conf(conf, cd, src_md, weights_md, dst_md, bias_md, attr);
conf.require_stateless_addressing = pd->has_large_buffers();
int oc_idx = (int)conf.with_groups;
auto *intel_engine = utils::downcast<intel::engine_t *>(engine);
switch (cd.prop_kind) {
case prop_kind::forward_training:
case prop_kind::forward_inference: {
conf.dispatch = intel_engine->create_dispatch(&dst_md);
conf.dispatch.define_dim("MB", 0, conf.mb);
conf.dispatch.define_dim("G", 1, conf.ngroups);
conf.dispatch.define_dim("OC", 1, conf.oc);
conf.dispatch.define_dim(
"OD", nstl::max(2, conf.ndims - 3), conf.od);
conf.dispatch.define_dim(
"OH", nstl::max(2, conf.ndims - 2), conf.oh);
conf.dispatch.define_dim(
"OW", nstl::max(2, conf.ndims - 1), conf.ow);
conf.dispatch.generate();
break;
}
case prop_kind::backward_data: {
conf.dispatch = intel_engine->create_dispatch(&src_md);
conf.dispatch.define_dim_with_nesting_level(
"IC", conf.ndims, conf.ic);
conf.dispatch.define_dim("MB", conf.mb);
conf.dispatch.define_dim("G", conf.ngroups);
conf.dispatch.define_dim(
"ID", nstl::max(2, conf.ndims - 3), conf.id);
conf.dispatch.define_dim(
"IH", nstl::max(2, conf.ndims - 2), conf.ih);
conf.dispatch.define_dim(
"IW", nstl::max(2, conf.ndims - 1), conf.iw);
conf.dispatch.generate();
break;
}
case prop_kind::backward_weights: {
conf.dispatch = intel_engine->create_dispatch(&weights_md);
conf.dispatch.define_dim("G", 0, conf.ngroups);
conf.dispatch.define_dim("OC", oc_idx, conf.oc);
conf.dispatch.define_dim("IC", oc_idx + 1, conf.ic);
conf.dispatch.define_dim(
"KD", oc_idx + nstl::max(2, conf.ndims - 3), conf.kd);
conf.dispatch.define_dim(
"KH", oc_idx + nstl::max(2, conf.ndims - 2), conf.kh);
conf.dispatch.define_dim(
"KW", oc_idx + nstl::max(2, conf.ndims - 1), conf.kw);
conf.dispatch.generate();
break;
}
default: break;
}
return status::success;
}
static status_t init_kernel_ctx_common(compute::kernel_ctx_t &kernel_ctx,
const conf_t &conf, const post_ops_t &post_ops,
const memory_desc_t *dst_md) {
kernel_ctx.require_stateless_addressing(conf.require_stateless_addressing);
kernel_ctx.define_int("NDIMS", conf.ndims);
kernel_ctx.define_int("G", conf.ngroups);
kernel_ctx.define_int("WITH_GROUPS", conf.with_groups);
kernel_ctx.define_int("MB", conf.mb);
kernel_ctx.define_int("IC", conf.ic);
kernel_ctx.define_int("ID", conf.id);
kernel_ctx.define_int("IH", conf.ih);
kernel_ctx.define_int("IW", conf.iw);
kernel_ctx.define_int("OC", conf.oc);
kernel_ctx.define_int("OD", conf.od);
kernel_ctx.define_int("OH", conf.oh);
kernel_ctx.define_int("OW", conf.ow);
kernel_ctx.define_int("KD", conf.kd);
kernel_ctx.define_int("KH", conf.kh);
kernel_ctx.define_int("KW", conf.kw);
kernel_ctx.define_int("SD", conf.stride_d);
kernel_ctx.define_int("SH", conf.stride_h);
kernel_ctx.define_int("SW", conf.stride_w);
kernel_ctx.define_int("PD", conf.f_pad);
kernel_ctx.define_int("PH", conf.t_pad);
kernel_ctx.define_int("PW", conf.l_pad);
kernel_ctx.define_int("PD_R", conf.back_pad);
kernel_ctx.define_int("PH_R", conf.b_pad);
kernel_ctx.define_int("PW_R", conf.r_pad);
kernel_ctx.define_int("DD", conf.dilate_d);
kernel_ctx.define_int("DH", conf.dilate_h);
kernel_ctx.define_int("DW", conf.dilate_w);
kernel_ctx.define_int("WITH_BIAS", conf.with_bias);
kernel_ctx.define_int("IS_FWD",
utils::one_of(conf.prop_kind, prop_kind::forward_inference,
prop_kind::forward_training));
kernel_ctx.define_int(
"IS_BWD_D", conf.prop_kind == prop_kind::backward_data);
kernel_ctx.define_int(
"IS_BWD_W", conf.prop_kind == prop_kind::backward_weights);
def_memory_desc_info(kernel_ctx, conf.src_md_info, "SRC", false);
def_memory_desc_info(kernel_ctx, conf.wei_md_info, "WEI", false);
def_memory_desc_info(kernel_ctx, conf.dst_md_info, "DST", false);
def_dispatch(kernel_ctx, conf.dispatch);
switch (conf.prop_kind) {
case prop_kind::forward_training:
case prop_kind::forward_inference:
kernel_ctx.set_data_type(conf.dst_data_type, false);
break;
case prop_kind::backward_data:
kernel_ctx.set_data_type(conf.src_data_type, false);
break;
case prop_kind::backward_weights:
kernel_ctx.set_data_type(conf.weights_data_type, false);
break;
default: break;
}
kernel_ctx.define_int("WITH_SROUND", conf.attr_info.with_dst_sround);
kernel_ctx.define_int("DST_DT_DIGITS",
dnnl::impl::types::digits<uint32_t>(conf.dst_data_type));
def_data_type(kernel_ctx, conf.src_data_type, "SRC", false);
def_data_type(kernel_ctx, conf.weights_data_type, "WEI", false);
def_data_type(kernel_ctx, conf.bias_data_type, "BIA", false);
def_data_type(kernel_ctx, conf.dst_data_type, "DST", false);
def_data_type(kernel_ctx, conf.acc_data_type, "ACC", false);
def_data_type(kernel_ctx,
conf.attr_info.sum_data_type == dnnl_data_type_undef
? conf.dst_data_type
: conf.attr_info.sum_data_type,
"SUM", false);
CHECK(def_attr_info(kernel_ctx, conf.attr_info, post_ops, *dst_md, false));
return status::success;
}
status_t ref_fwd_t::pd_t::init_conf(impl::engine_t *engine) {
CHECK(init_conf_common(conf, this, engine));
return status::success;
}
status_t ref_fwd_t::pd_t::init_kernel_ctx(
compute::kernel_ctx_t &kernel_ctx) const {
return init_kernel_ctx_common(
kernel_ctx, conf, attr()->post_ops_, invariant_dst_md());
}
status_t ref_fwd_t::execute_forward(const exec_ctx_t &ctx) const {
status_t status = status::success;
auto &src = CTX_IN_STORAGE(DNNL_ARG_SRC);
auto &weights = CTX_IN_STORAGE(DNNL_ARG_WEIGHTS);
auto &bias = CTX_IN_STORAGE(DNNL_ARG_BIAS);
auto &dst = CTX_OUT_CLEAN_STORAGE(DNNL_ARG_DST, status);
CHECK(status);
auto &src_scales = CTX_IN_STORAGE(DNNL_ARG_ATTR_SCALES | DNNL_ARG_SRC);
auto &wei_scales = CTX_IN_STORAGE(DNNL_ARG_ATTR_SCALES | DNNL_ARG_WEIGHTS);
auto &dst_scales = CTX_IN_STORAGE(DNNL_ARG_ATTR_SCALES | DNNL_ARG_DST);
auto &src_zpoints
= CTX_IN_STORAGE(DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_SRC);
auto &wei_zpoints
= CTX_IN_STORAGE(DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_WEIGHTS);
auto &dst_zpoints
= CTX_IN_STORAGE(DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_DST);
auto &dst_sround = CTX_IN_STORAGE(DNNL_ARG_ATTR_ROUNDING_SEED);
auto &conf = pd()->conf;
const bool subbyte_pack = pd()->subbyte_pack_;
const auto c_d = ctx.memory_mdw(DNNL_ARG_DST, pd()->dst_md());
const dim_t nelems = c_d.nelems();
auto tmp = ctx.get_scratchpad_grantor().get_memory_storage(
memory_tracking::names::key_conv_pack_space);
compute::kernel_arg_list_t arg_list;
arg_list.set(0, src);
arg_list.set(1, weights);
arg_list.set(2, bias);
arg_list.set(3, subbyte_pack ? *tmp : dst);
unsigned arg_idx = append_post_ops_to_arg_list(
ctx, arg_list, 4, pd()->attr()->post_ops_, *pd()->dst_md());
arg_list.set(arg_idx++, src_scales);
arg_list.set(arg_idx++, wei_scales);
arg_list.set(arg_idx++, dst_scales);
if (conf.attr_info.with_src_zpoints)
arg_list.set(arg_idx++, src_zpoints);
else
arg_list.set(arg_idx++, memory_storage_t::empty_storage());
if (conf.attr_info.with_wei_zpoints)
arg_list.set(arg_idx++, wei_zpoints);
else
arg_list.set(arg_idx++, memory_storage_t::empty_storage());
if (conf.attr_info.with_dst_zpoints)
arg_list.set(arg_idx++, dst_zpoints);
else
arg_list.set(arg_idx++, memory_storage_t::empty_storage());
if (conf.attr_info.with_dst_sround) arg_list.set(arg_idx++, dst_sround);
auto nd_range = pd()->conf.dispatch.nd_range();
CHECK(parallel_for(ctx, nd_range, kernels_[0], arg_list));
if (!subbyte_pack) return status::success;
compute::kernel_arg_list_t repack_arg_list;
repack_arg_list.set(0, *tmp);
repack_arg_list.set(1, dst);
repack_arg_list.set(2, into<dim_t>(nelems));
repack_arg_list.set(3, 4);
compute::range_t repack_gws((nelems * 4 + 7) / 8);
compute::nd_range_t repack_nd_range(repack_gws);
return large_parallel_for(
ctx, repack_nd_range, kernels_[1], repack_arg_list, 4);
}
status_t ref_bwd_data_t::pd_t::init_conf(impl::engine_t *engine) {
CHECK(init_conf_common(conf, this, engine));
return status::success;
}
status_t ref_bwd_data_t::pd_t::init_kernel_ctx(
compute::kernel_ctx_t &kernel_ctx) const {
return init_kernel_ctx_common(
kernel_ctx, conf, attr()->post_ops_, invariant_src_md());
}
status_t ref_bwd_data_t::execute_backward_data(const exec_ctx_t &ctx) const {
status_t status = status::success;
auto &diff_dst = CTX_IN_STORAGE(DNNL_ARG_DIFF_DST);
auto &weights = CTX_IN_STORAGE(DNNL_ARG_WEIGHTS);
auto &diff_src = CTX_OUT_CLEAN_STORAGE(DNNL_ARG_DIFF_SRC, status);
CHECK(status);
auto &bias = CTX_IN_STORAGE(DNNL_ARG_BIAS);
auto &src_scales = CTX_IN_STORAGE(DNNL_ARG_ATTR_SCALES | DNNL_ARG_SRC);
auto &wei_scales = CTX_IN_STORAGE(DNNL_ARG_ATTR_SCALES | DNNL_ARG_WEIGHTS);
auto &dst_scales = CTX_IN_STORAGE(DNNL_ARG_ATTR_SCALES | DNNL_ARG_DST);
auto &src_zpoints
= CTX_IN_STORAGE(DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_SRC);
auto &wei_zpoints
= CTX_IN_STORAGE(DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_WEIGHTS);
auto &dst_zpoints
= CTX_IN_STORAGE(DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_DST);
auto &conf = pd()->conf;
const bool subbyte_pack = pd()->subbyte_pack_;
const auto c_d = ctx.memory_mdw(DNNL_ARG_DIFF_DST, pd()->diff_dst_md());
const dim_t nelems = c_d.nelems();
auto tmp = ctx.get_scratchpad_grantor().get_memory_storage(
memory_tracking::names::key_conv_pack_space);
compute::kernel_arg_list_t arg_list;
arg_list.set(0, subbyte_pack ? *tmp : diff_src);
arg_list.set(1, weights);
arg_list.set(2, diff_dst);
arg_list.set(3, bias);
unsigned arg_idx = append_post_ops_to_arg_list(
ctx, arg_list, 4, pd()->attr()->post_ops_, *pd()->dst_md());
arg_list.set(arg_idx++, src_scales);
arg_list.set(arg_idx++, wei_scales);
arg_list.set(arg_idx++, dst_scales);
if (conf.attr_info.with_src_zpoints)
arg_list.set(arg_idx++, src_zpoints);
else
arg_list.set(arg_idx++, memory_storage_t::empty_storage());
if (conf.attr_info.with_wei_zpoints)
arg_list.set(arg_idx++, wei_zpoints);
else
arg_list.set(arg_idx++, memory_storage_t::empty_storage());
if (conf.attr_info.with_dst_zpoints)
arg_list.set(arg_idx++, dst_zpoints);
else
arg_list.set(arg_idx++, memory_storage_t::empty_storage());
auto nd_range = pd()->conf.dispatch.nd_range();
CHECK(parallel_for(ctx, nd_range, kernels_[0], arg_list));
if (!subbyte_pack) return status::success;
compute::kernel_arg_list_t repack_arg_list;
repack_arg_list.set(0, *tmp);
repack_arg_list.set(1, diff_src);
repack_arg_list.set(2, into<dim_t>(nelems));
repack_arg_list.set(3, 4);
compute::range_t repack_gws((nelems * 4 + 7) / 8);
compute::nd_range_t repack_nd_range(repack_gws);
return large_parallel_for(
ctx, repack_nd_range, kernels_[1], repack_arg_list, 4);
}
status_t ref_bwd_weights_t::pd_t::init_conf(impl::engine_t *engine) {
return init_conf_common(conf, this, engine);
}
status_t ref_bwd_weights_t::pd_t::init_kernel_ctx(
compute::kernel_ctx_t &kernel_ctx) const {
return init_kernel_ctx_common(
kernel_ctx, conf, attr()->post_ops_, invariant_wei_md());
}
status_t ref_bwd_weights_t::execute_backward_weights(
const exec_ctx_t &ctx) const {
status_t status = status::success;
auto &src = CTX_IN_STORAGE(DNNL_ARG_SRC);
auto &diff_dst = CTX_IN_STORAGE(DNNL_ARG_DIFF_DST);
auto &diff_weights = CTX_OUT_CLEAN_STORAGE(DNNL_ARG_DIFF_WEIGHTS, status);
CHECK(status);
auto &diff_bias = CTX_OUT_CLEAN_STORAGE(DNNL_ARG_DIFF_BIAS, status);
CHECK(status);
const bool subbyte_pack = pd()->subbyte_pack_;
const auto c_d
= ctx.memory_mdw(DNNL_ARG_DIFF_WEIGHTS, pd()->diff_weights_md());
const dim_t nelems = c_d.nelems();
auto tmp = ctx.get_scratchpad_grantor().get_memory_storage(
memory_tracking::names::key_conv_pack_space);
compute::kernel_arg_list_t arg_list;
arg_list.set(0, src);
arg_list.set(1, subbyte_pack ? *tmp : diff_weights);
arg_list.set(2, diff_bias);
arg_list.set(3, diff_dst);
auto nd_range = pd()->conf.dispatch.nd_range();
CHECK(parallel_for(ctx, nd_range, kernels_[0], arg_list));
if (!subbyte_pack) return status::success;
compute::kernel_arg_list_t repack_arg_list;
repack_arg_list.set(0, *tmp);
repack_arg_list.set(1, diff_weights);
repack_arg_list.set(2, into<dim_t>(nelems));
repack_arg_list.set(3, 4);
compute::range_t repack_gws((nelems * 4 + 7) / 8);
compute::nd_range_t repack_nd_range(repack_gws);
return large_parallel_for(
ctx, repack_nd_range, kernels_[1], repack_arg_list, 4);
}
} } } } }