[GPU] integration oneDNN3.0 (#14647)
* Support oneDNN3.0 API
* Use binary_mul post_opt instead of oscale channel-wise mask(2)
* Disable some post-opt fusing because of no eltwise scale API
eltw(non_linear)+eltw(linear), eltw+sum+eltw(linear)
* Fix hardwish issue in 3.0
hard coded hardswish parameter(2.7) is changed alpha and beta from user's required input.
Signed-off-by: hyunback <hyunback.kim@intel.com>
This commit is contained in:
1 parent
0c9abf43a9
commit
e75fa049ac
18 files changed
+446
-480
No files matched your search
@@ -34,16 +34,17 @@ void select_preferred_formats::run(program& p) {
|
||||
for (auto n : p.get_processing_order()) {
|
||||
// Onednn primitive descriptor creation may fail, for example, due to asymmetric weight.
|
||||
try {
|
||||
dnnl::primitive_desc prim_desc;
|
||||
if (n->is_type<convolution>()) {
|
||||
auto desc = onednn::get_convolution_descriptor(*n->get_kernel_impl_params(), dnnl::memory::format_tag::any);
|
||||
prim_desc = dnnl::primitive_desc(&desc->data, nullptr, engine.get_onednn_engine(), nullptr);
|
||||
auto prim_desc = onednn::get_convolution_primitive_descriptor(*n->get_kernel_impl_params(),
|
||||
dnnl::primitive_attr(),
|
||||
dnnl::memory::format_tag::any);
|
||||
_lo.select_preferred_formats_for_onednn(*n, *prim_desc);
|
||||
} else if (n->is_type<deconvolution>()) {
|
||||
auto desc = onednn::get_deconvolution_descriptor(*n->get_kernel_impl_params(), dnnl::memory::format_tag::any);
|
||||
prim_desc = dnnl::primitive_desc(&desc->data, nullptr, engine.get_onednn_engine(), nullptr);
|
||||
auto prim_desc = onednn::get_deconvolution_primitive_descriptor(*n->get_kernel_impl_params(),
|
||||
dnnl::primitive_attr(),
|
||||
dnnl::memory::format_tag::any);
|
||||
_lo.select_preferred_formats_for_onednn(*n, *prim_desc);
|
||||
}
|
||||
|
||||
_lo.select_preferred_formats_for_onednn(*n, prim_desc);
|
||||
} catch(std::exception &exception) {
|
||||
GPU_DEBUG_INFO << "WARNING(select_preferred_formats): " << exception.what() << std::endl;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct concatenation_onednn : typed_primitive_onednn_impl<concatenation, void, dnnl::concat::primitive_desc, dnnl::concat> {
|
||||
using parent = typed_primitive_onednn_impl<concatenation, void, dnnl::concat::primitive_desc, dnnl::concat>;
|
||||
struct concatenation_onednn : typed_primitive_onednn_impl<concatenation, dnnl::concat::primitive_desc, dnnl::concat> {
|
||||
using parent = typed_primitive_onednn_impl<concatenation, dnnl::concat::primitive_desc, dnnl::concat>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -49,23 +49,26 @@ protected:
|
||||
return args;
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::concat::primitive_desc> get_concatenation_descriptor(const kernel_impl_params& impl_params,
|
||||
const int64_t axis,
|
||||
const cldnn::engine& engine) {
|
||||
static std::shared_ptr<dnnl::concat::primitive_desc> get_concatenation_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr,
|
||||
const int64_t axis) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
std::vector<dnnl::memory::desc> input_mds;
|
||||
for (size_t i = 0; i < impl_params.input_layouts.size(); i++) {
|
||||
input_mds.push_back(onednn::layout_to_memory_desc(impl_params.get_input_layout(i)));
|
||||
}
|
||||
auto output_md = onednn::layout_to_memory_desc(impl_params.get_output_layout());
|
||||
return std::make_shared<dnnl::concat::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
output_md,
|
||||
axis,
|
||||
input_mds,
|
||||
engine.get_onednn_engine());
|
||||
attr);
|
||||
}
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
if (_prim.get(true) == nullptr) {
|
||||
ob << false;
|
||||
return;
|
||||
@@ -82,9 +85,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
bool has_prim;
|
||||
ib >> has_prim;
|
||||
|
||||
@@ -104,6 +109,7 @@ public:
|
||||
ib >> prim_cache;
|
||||
|
||||
_prim = dnnl::concat(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const concatenation_node& arg, const kernel_impl_params& impl_params) {
|
||||
@@ -112,12 +118,10 @@ public:
|
||||
if (arg.can_be_optimized())
|
||||
return make_unique<concatenation_onednn>(engine);
|
||||
auto prim = impl_params.typed_desc<concatenation>();
|
||||
auto desc = get_concatenation_descriptor(impl_params, prim->axis, impl_params.prog->get_engine());
|
||||
auto attr = arg.get_onednn_primitive_attributes();
|
||||
auto prim_desc = get_concatenation_primitive_descriptor(impl_params, *attr, prim->axis);
|
||||
|
||||
std::shared_ptr<void> dummy = nullptr;
|
||||
|
||||
return cldnn::make_unique<concatenation_onednn>(engine, config, dummy, attr, *desc);
|
||||
return cldnn::make_unique<concatenation_onednn>(engine, config, attr, *prim_desc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct convolution_onednn : typed_primitive_onednn_impl<convolution, dnnl::convolution_forward::desc> {
|
||||
using parent = typed_primitive_onednn_impl<convolution, dnnl::convolution_forward::desc>;
|
||||
struct convolution_onednn : typed_primitive_onednn_impl<convolution> {
|
||||
using parent = typed_primitive_onednn_impl<convolution>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -46,7 +46,7 @@ protected:
|
||||
args.insert({DNNL_ARG_BIAS, bias->get_onednn_memory(_pd.weights_desc(1))});
|
||||
}
|
||||
|
||||
if (has_zero_points(DNNL_ARG_SRC, _attrs)) {
|
||||
if (instance.activations_zero_points_term()) {
|
||||
auto a_zp = instance.activations_zero_points_memory();
|
||||
dnnl::memory::desc desc = onednn::layout_to_memory_desc(a_zp->get_layout(), dnnl::memory::format_tag::a, true);
|
||||
args.insert({DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_SRC, a_zp->get_onednn_memory(desc)});
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
if (has_zero_points(DNNL_ARG_WEIGHTS, _attrs)) {
|
||||
if (instance.weights_zero_points_term()) {
|
||||
auto w_zp = instance.weights_zero_points_memory();
|
||||
dnnl::memory::desc desc = onednn::layout_to_memory_desc(w_zp->get_layout(), dnnl::memory::format_tag::a, true);
|
||||
args.insert({DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_WEIGHTS, w_zp->get_onednn_memory(desc)});
|
||||
@@ -87,13 +87,9 @@ protected:
|
||||
static void set_activation_zero_points_attr(const std::shared_ptr<dnnl::primitive_attr>& attrs, cldnn::data_node& node) {
|
||||
int32_t zp_val = DNNL_RUNTIME_S32_VAL;
|
||||
bool is_per_tensor = onednn::is_per_tensor<T>(node, zp_val);
|
||||
if (is_per_tensor) {
|
||||
attrs->set_zero_points(DNNL_ARG_SRC, 0, {zp_val});
|
||||
} else {
|
||||
memory::ptr s32_mem = onednn::convert_zp_data_to_s32<T>(node.get_attached_memory_ptr());
|
||||
node.attach_memory(s32_mem, false);
|
||||
attrs->set_zero_points(DNNL_ARG_SRC, 2, {DNNL_RUNTIME_S32_VAL});
|
||||
}
|
||||
memory::ptr s32_mem = onednn::convert_zp_data_to_s32<T>(node.get_attached_memory_ptr());
|
||||
node.attach_memory(s32_mem, false);
|
||||
attrs->set_zero_points_mask(DNNL_ARG_SRC, is_per_tensor ? 0 : 2);
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::primitive_attr> get_primitive_attributes(const typed_program_node<convolution>& arg) {
|
||||
@@ -163,6 +159,7 @@ protected:
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
ob << make_data(&_desc->data, sizeof(dnnl_convolution_desc_t));
|
||||
@@ -170,9 +167,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
const char dummy_mem[sizeof(dnnl::convolution_forward::desc)] = {};
|
||||
@@ -186,16 +185,17 @@ public:
|
||||
|
||||
_pd = dnnl::primitive_desc(&_desc->data, _attrs.get(), ib.get_engine().get_onednn_engine(), nullptr);
|
||||
_prim = dnnl::primitive(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const convolution_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto desc = get_convolution_descriptor(impl_params);
|
||||
auto attr = get_primitive_attributes(arg);
|
||||
dnnl::primitive_desc prim_desc{&desc->data, attr.get(), engine.get_onednn_engine(), nullptr};
|
||||
|
||||
return cldnn::make_unique<convolution_onednn>(engine, config, desc, attr, prim_desc, get_weights_reorder(impl_params, prim_desc, arg.get_transposed()));
|
||||
auto prim_desc = get_convolution_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
return cldnn::make_unique<convolution_onednn>(engine, config, attr, *prim_desc, get_weights_reorder(impl_params, *prim_desc, arg.get_transposed()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
static std::shared_ptr<dnnl::convolution_forward::desc> get_convolution_descriptor(const kernel_impl_params& impl_params,
|
||||
static std::shared_ptr<dnnl::convolution_forward::primitive_desc> get_convolution_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr = dnnl::primitive_attr(),
|
||||
dnnl::memory::format_tag tag_in_out = dnnl::memory::format_tag::undef) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<convolution>();
|
||||
|
||||
auto input_layout = impl_params.get_input_layout(0);
|
||||
@@ -28,16 +30,17 @@ static std::shared_ptr<dnnl::convolution_forward::desc> get_convolution_descript
|
||||
for (size_t i = 0; i < dilation.size(); i++) {
|
||||
dilation[i]--;
|
||||
int weights_offset = (grouped_weights ? 3 : 2) + static_cast<int>(i);
|
||||
auto os = output_md.dims()[2 + i];
|
||||
auto is = input_md.dims()[2 + i];
|
||||
auto ks = weights_md.dims()[weights_offset];
|
||||
auto os = output_md.get_dims()[2 + i];
|
||||
auto is = input_md.get_dims()[2 + i];
|
||||
auto ks = weights_md.get_dims()[weights_offset];
|
||||
auto kernel_range = 1 + (ks - 1) * (dilation[i] + 1);
|
||||
pad_r[i] = (os - 1) * stride[i] - is + kernel_range - pad_l[i];
|
||||
}
|
||||
|
||||
if (!prim->bias.empty()) {
|
||||
auto bias_md = onednn::layout_to_memory_desc(impl_params.get_input_layout(2), dnnl::memory::format_tag::any, true);
|
||||
return std::make_shared<dnnl::convolution_forward::desc>(
|
||||
return std::make_shared<dnnl::convolution_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
dnnl::algorithm::convolution_direct,
|
||||
input_md,
|
||||
@@ -47,9 +50,11 @@ static std::shared_ptr<dnnl::convolution_forward::desc> get_convolution_descript
|
||||
stride,
|
||||
dilation,
|
||||
pad_l,
|
||||
pad_r);
|
||||
pad_r,
|
||||
attr);
|
||||
} else {
|
||||
return std::make_shared<dnnl::convolution_forward::desc>(
|
||||
return std::make_shared<dnnl::convolution_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
dnnl::algorithm::convolution_direct,
|
||||
input_md,
|
||||
@@ -58,7 +63,8 @@ static std::shared_ptr<dnnl::convolution_forward::desc> get_convolution_descript
|
||||
stride,
|
||||
dilation,
|
||||
pad_l,
|
||||
pad_r);
|
||||
pad_r,
|
||||
attr);
|
||||
}
|
||||
}
|
||||
} // namespace onednn
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct deconvolution_onednn : typed_primitive_onednn_impl<deconvolution, dnnl::deconvolution_forward::desc> {
|
||||
using parent = typed_primitive_onednn_impl<deconvolution, dnnl::deconvolution_forward::desc>;
|
||||
struct deconvolution_onednn : typed_primitive_onednn_impl<deconvolution> {
|
||||
using parent = typed_primitive_onednn_impl<deconvolution>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -48,9 +48,7 @@ protected:
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::primitive_attr> get_primitive_attributes(const typed_program_node<deconvolution>& arg) {
|
||||
auto attrs = arg.get_onednn_primitive_attributes();
|
||||
|
||||
return attrs;
|
||||
return arg.get_onednn_primitive_attributes();
|
||||
}
|
||||
|
||||
static kernel_selector::WeightsReorderParams get_weights_reorder(const kernel_impl_params& impl_params, const dnnl::primitive_desc& pd) {
|
||||
@@ -88,6 +86,7 @@ protected:
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
ob << make_data(&_desc->data, sizeof(dnnl_deconvolution_desc_t));
|
||||
@@ -95,9 +94,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
const char dummy_mem[sizeof(dnnl::deconvolution_forward::desc)] = {};
|
||||
@@ -111,16 +112,16 @@ public:
|
||||
|
||||
_pd = dnnl::primitive_desc(&_desc->data, _attrs.get(), ib.get_engine().get_onednn_engine(), nullptr);
|
||||
_prim = dnnl::primitive(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const deconvolution_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto desc = get_deconvolution_descriptor(impl_params);
|
||||
auto attr = get_primitive_attributes(arg);
|
||||
dnnl::primitive_desc prim_desc{&desc->data, attr.get(), engine.get_onednn_engine(), nullptr};
|
||||
auto prim_desc = get_deconvolution_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
return cldnn::make_unique<deconvolution_onednn>(engine, config, desc, attr, prim_desc, get_weights_reorder(impl_params, prim_desc));
|
||||
return cldnn::make_unique<deconvolution_onednn>(engine, config, attr, *prim_desc, get_weights_reorder(impl_params, *prim_desc));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
static std::shared_ptr<dnnl::deconvolution_forward::desc> get_deconvolution_descriptor(const kernel_impl_params& impl_params,
|
||||
static std::shared_ptr<dnnl::deconvolution_forward::primitive_desc> get_deconvolution_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr = dnnl::primitive_attr(),
|
||||
dnnl::memory::format_tag tag_in_out = dnnl::memory::format_tag::undef) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<deconvolution>();
|
||||
|
||||
auto input_layout = impl_params.get_input_layout(0);
|
||||
@@ -27,16 +29,17 @@ static std::shared_ptr<dnnl::deconvolution_forward::desc> get_deconvolution_desc
|
||||
for (size_t i = 0; i < dilation.size(); i++) {
|
||||
dilation[i]--;
|
||||
int weights_offset = (grouped_weights ? 3 : 2) + static_cast<int>(i);
|
||||
auto os = output_md.dims()[2 + i];
|
||||
auto is = input_md.dims()[2 + i];
|
||||
auto ks = weights_md.dims()[weights_offset];
|
||||
auto os = output_md.get_dims()[2 + i];
|
||||
auto is = input_md.get_dims()[2 + i];
|
||||
auto ks = weights_md.get_dims()[weights_offset];
|
||||
auto kernel_range = 1 + (ks - 1) * (dilation[i] + 1);
|
||||
pad_r[i] = (is - 1) * stride[i] - os + kernel_range - pad_l[i];
|
||||
}
|
||||
|
||||
if (!prim->bias.empty()) {
|
||||
auto bias_md = onednn::layout_to_memory_desc(impl_params.get_input_layout(2), dnnl::memory::format_tag::any, true);
|
||||
return std::make_shared<dnnl::deconvolution_forward::desc>(
|
||||
return std::make_shared<dnnl::deconvolution_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
dnnl::algorithm::deconvolution_direct,
|
||||
input_md,
|
||||
@@ -46,9 +49,11 @@ static std::shared_ptr<dnnl::deconvolution_forward::desc> get_deconvolution_desc
|
||||
stride,
|
||||
dilation,
|
||||
pad_l,
|
||||
pad_r);
|
||||
pad_r,
|
||||
attr);
|
||||
} else {
|
||||
return std::make_shared<dnnl::deconvolution_forward::desc>(
|
||||
return std::make_shared<dnnl::deconvolution_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
dnnl::algorithm::deconvolution_direct,
|
||||
input_md,
|
||||
@@ -57,7 +62,8 @@ static std::shared_ptr<dnnl::deconvolution_forward::desc> get_deconvolution_desc
|
||||
stride,
|
||||
dilation,
|
||||
pad_l,
|
||||
pad_r);
|
||||
pad_r,
|
||||
attr);
|
||||
}
|
||||
}
|
||||
} // namespace onednn
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct fully_connected_onednn : typed_primitive_onednn_impl<fully_connected, dnnl::inner_product_forward::desc> {
|
||||
using parent = typed_primitive_onednn_impl<fully_connected, dnnl::inner_product_forward::desc>;
|
||||
struct fully_connected_onednn : typed_primitive_onednn_impl<fully_connected> {
|
||||
using parent = typed_primitive_onednn_impl<fully_connected>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -95,7 +95,9 @@ protected:
|
||||
return weights_reorder_params;
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::inner_product_forward::desc> get_fully_connected_descriptor(const kernel_impl_params& impl_params) {
|
||||
static std::shared_ptr<dnnl::inner_product_forward::primitive_desc> get_fully_connected_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr = dnnl::primitive_attr()) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<fully_connected>();
|
||||
|
||||
auto input_layout = impl_params.get_input_layout(0);
|
||||
@@ -133,23 +135,28 @@ protected:
|
||||
|
||||
if (!prim->bias.empty()) {
|
||||
auto bias_md = onednn::layout_to_memory_desc(impl_params.get_input_layout(2), dnnl::memory::format_tag::any, true);
|
||||
return std::make_shared<dnnl::inner_product_forward::desc>(
|
||||
return std::make_shared<dnnl::inner_product_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
input_md,
|
||||
weights_md,
|
||||
bias_md,
|
||||
output_md);
|
||||
output_md,
|
||||
attr);
|
||||
} else {
|
||||
return std::make_shared<dnnl::inner_product_forward::desc>(
|
||||
return std::make_shared<dnnl::inner_product_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
input_md,
|
||||
weights_md,
|
||||
output_md);
|
||||
output_md,
|
||||
attr);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
ob << make_data(&_desc->data, sizeof(dnnl_inner_product_desc_t));
|
||||
@@ -157,9 +164,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
const char dummy_mem[sizeof(dnnl::inner_product_forward::desc)] = {};
|
||||
@@ -173,16 +182,16 @@ public:
|
||||
|
||||
_pd = dnnl::primitive_desc(&_desc->data, _attrs.get(), ib.get_engine().get_onednn_engine(), nullptr);
|
||||
_prim = dnnl::primitive(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const fully_connected_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto desc = get_fully_connected_descriptor(impl_params);
|
||||
auto attr = arg.get_onednn_primitive_attributes();
|
||||
dnnl::primitive_desc prim_desc{&desc->data, attr.get(), engine.get_onednn_engine(), nullptr};
|
||||
auto prim_desc = get_fully_connected_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
return cldnn::make_unique<fully_connected_onednn>(engine, config, desc, attr, prim_desc, get_weights_reorder(impl_params, prim_desc));
|
||||
return cldnn::make_unique<fully_connected_onednn>(engine, config, attr, *prim_desc, get_weights_reorder(impl_params, *prim_desc));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct gemm_onednn : typed_primitive_onednn_impl<gemm, dnnl::matmul::desc> {
|
||||
using parent = typed_primitive_onednn_impl<gemm, dnnl::matmul::desc>;
|
||||
struct gemm_onednn : typed_primitive_onednn_impl<gemm> {
|
||||
using parent = typed_primitive_onednn_impl<gemm>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -53,7 +53,9 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::matmul::desc> get_gemm_descriptor(const kernel_impl_params& impl_params) {
|
||||
static std::shared_ptr<dnnl::matmul::primitive_desc> get_gemm_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr = dnnl::primitive_attr()) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<gemm>();
|
||||
auto gemm_with_bias = prim->dependencies().size() == 3;
|
||||
auto out_l = impl_params.get_output_layout();
|
||||
@@ -116,21 +118,26 @@ protected:
|
||||
dnnl::memory::format_tag bias_fmt = onednn::convert_gemm_data_format(bias_dims);
|
||||
dnnl::memory::desc bias_md(bias_dims, bias_dt, bias_fmt);
|
||||
|
||||
return std::make_shared<dnnl::matmul::desc>(
|
||||
return std::make_shared<dnnl::matmul::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
in0_md,
|
||||
in1_md,
|
||||
bias_md,
|
||||
out_md);
|
||||
out_md,
|
||||
attr);
|
||||
} else {
|
||||
return std::make_shared<dnnl::matmul::desc>(
|
||||
return std::make_shared<dnnl::matmul::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
in0_md,
|
||||
in1_md,
|
||||
out_md);
|
||||
out_md,
|
||||
attr);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
ob << make_data(&_desc->data, sizeof(dnnl_matmul_desc_t));
|
||||
@@ -138,9 +145,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
const char dummy_mem[sizeof(dnnl::matmul::desc)] = {};
|
||||
@@ -154,16 +163,16 @@ public:
|
||||
|
||||
_pd = dnnl::primitive_desc(&_desc->data, _attrs.get(), ib.get_engine().get_onednn_engine(), nullptr);
|
||||
_prim = dnnl::primitive(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const gemm_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto desc = get_gemm_descriptor(impl_params);
|
||||
auto attr = arg.get_onednn_primitive_attributes();
|
||||
dnnl::primitive_desc prim_desc{&desc->data, attr.get(), engine.get_onednn_engine(), nullptr};
|
||||
auto prim_desc = get_gemm_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
return cldnn::make_unique<gemm_onednn>(engine, config, desc, attr, prim_desc);
|
||||
return cldnn::make_unique<gemm_onednn>(engine, config, attr, *prim_desc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct pooling_onednn : typed_primitive_onednn_impl<pooling, dnnl::pooling_forward::desc> {
|
||||
using parent = typed_primitive_onednn_impl<pooling, dnnl::pooling_forward::desc>;
|
||||
struct pooling_onednn : typed_primitive_onednn_impl<pooling> {
|
||||
using parent = typed_primitive_onednn_impl<pooling>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -26,7 +26,9 @@ protected:
|
||||
return make_unique<pooling_onednn>(*this);
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::pooling_forward::desc> get_pooling_descriptor(const kernel_impl_params& impl_params) {
|
||||
static std::shared_ptr<dnnl::pooling_forward::primitive_desc> get_pooling_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr = dnnl::primitive_attr()) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<pooling>();
|
||||
|
||||
auto input_layout = impl_params.get_input_layout(0);
|
||||
@@ -36,45 +38,53 @@ protected:
|
||||
auto stride_shape = prim->stride;
|
||||
auto pads_begin_shape = prim->pads_begin;
|
||||
auto pads_end_shape = prim->pads_end;
|
||||
auto dilation_shape = prim->dilation;
|
||||
if (dilation_shape.empty()) dilation_shape.resize(stride_shape.size(), 0);
|
||||
|
||||
kernel_shape.resize(std::max<size_t>(2, prim->size.size()), 1);
|
||||
stride_shape.resize(std::max<size_t>(2, prim->stride.size()), 1);
|
||||
pads_begin_shape.resize(std::max<size_t>(2, prim->pads_begin.size()), 0);
|
||||
pads_end_shape.resize(std::max<size_t>(2, prim->pads_end.size()), 0);
|
||||
dilation_shape.resize(std::max<size_t>(2, dilation_shape.size()), 0);
|
||||
|
||||
dnnl::memory::dims stride(stride_shape.begin(), stride_shape.end());
|
||||
dnnl::memory::dims kernel(kernel_shape.begin(), kernel_shape.end());
|
||||
dnnl::memory::dims pad_l(pads_begin_shape.begin(), pads_begin_shape.end());
|
||||
dnnl::memory::dims pad_r(pads_end_shape.begin(), pads_end_shape.end());
|
||||
dnnl::memory::dims dilation(dilation_shape.begin(), dilation_shape.end());
|
||||
|
||||
auto input_md = onednn::layout_to_memory_desc(input_layout);
|
||||
auto output_md = onednn::layout_to_memory_desc(output_layout);
|
||||
|
||||
for (size_t i = 0; i < kernel.size(); i++) {
|
||||
pad_r[i] = (output_md.dims()[2 + i] - 1) * stride[i] - input_md.dims()[2 + i] + kernel[i] - pad_l[i];
|
||||
pad_r[i] = (output_md.get_dims()[2 + i] - 1) * stride[i] - input_md.get_dims()[2 + i] + kernel[i] - pad_l[i];
|
||||
}
|
||||
|
||||
dnnl::algorithm alg;
|
||||
switch (prim->mode) {
|
||||
case pooling_mode::average: alg = dnnl::algorithm::pooling_avg; break;
|
||||
case pooling_mode::average: alg = dnnl::algorithm::pooling_avg_include_padding; break;
|
||||
case pooling_mode::max: alg = dnnl::algorithm::pooling_max; break;
|
||||
case pooling_mode::average_no_padding: alg = dnnl::algorithm::pooling_avg_exclude_padding; break;
|
||||
default: throw std::runtime_error("unsupported pool mode");
|
||||
}
|
||||
|
||||
return std::make_shared<dnnl::pooling_forward::desc>(
|
||||
return std::make_shared<dnnl::pooling_forward::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
dnnl::prop_kind::forward_inference,
|
||||
alg,
|
||||
input_md,
|
||||
output_md,
|
||||
stride,
|
||||
kernel,
|
||||
dilation,
|
||||
pad_l,
|
||||
pad_r);
|
||||
pad_r,
|
||||
attr);
|
||||
}
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
ob << make_data(&_desc->data, sizeof(dnnl_pooling_desc_t));
|
||||
@@ -82,9 +92,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
const char dummy_mem[sizeof(dnnl::pooling_forward::desc)] = {};
|
||||
@@ -98,16 +110,16 @@ public:
|
||||
|
||||
_pd = dnnl::primitive_desc(&_desc->data, _attrs.get(), ib.get_engine().get_onednn_engine(), nullptr);
|
||||
_prim = dnnl::primitive(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const pooling_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto desc = get_pooling_descriptor(impl_params);
|
||||
auto attr = arg.get_onednn_primitive_attributes();
|
||||
dnnl::primitive_desc prim_desc{&desc->data, attr.get(), engine.get_onednn_engine(), nullptr};
|
||||
auto prim_desc = get_pooling_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
return cldnn::make_unique<pooling_onednn>(engine, config, desc, attr, prim_desc);
|
||||
return cldnn::make_unique<pooling_onednn>(engine, config, attr, *prim_desc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -30,10 +30,9 @@ namespace onednn {
|
||||
|
||||
static std::mutex cacheAccessMutex;
|
||||
|
||||
template <class PType, class DescType, class PrimDescType = dnnl::primitive_desc, class PrimType = dnnl::primitive>
|
||||
template <class PType, class PrimDescType = dnnl::primitive_desc, class PrimType = dnnl::primitive>
|
||||
struct typed_primitive_onednn_impl : public typed_primitive_impl<PType> {
|
||||
const engine* _engine;
|
||||
std::shared_ptr<DescType> _desc;
|
||||
std::shared_ptr<dnnl::primitive_attr> _attrs;
|
||||
PrimDescType _pd;
|
||||
PrimType _prim;
|
||||
@@ -41,13 +40,11 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl<PType> {
|
||||
|
||||
typed_primitive_onednn_impl(const engine& engine,
|
||||
const ExecutionConfig& config,
|
||||
std::shared_ptr<DescType> desc,
|
||||
std::shared_ptr<dnnl::primitive_attr> attrs,
|
||||
const PrimDescType& pd,
|
||||
kernel_selector::WeightsReorderParams weights_reorder = {})
|
||||
: typed_primitive_impl<PType>(weights_reorder, pd.impl_info_str()),
|
||||
_engine(&engine),
|
||||
_desc(desc),
|
||||
_attrs(attrs),
|
||||
_pd(pd) {
|
||||
build_primitive(config);
|
||||
@@ -62,7 +59,7 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl<PType> {
|
||||
|
||||
typed_primitive_onednn_impl()
|
||||
: typed_primitive_impl<PType>({}, "undef"),
|
||||
_desc(nullptr), _pd(), _prim() {
|
||||
_pd(), _prim() {
|
||||
_attrs = std::make_shared<dnnl::primitive_attr>();
|
||||
}
|
||||
|
||||
@@ -73,6 +70,7 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl<PType> {
|
||||
// [ dnnl::primitive_desc ]
|
||||
// [ dnnl::cache_blob ]
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
if (_attrs.get() == nullptr) {
|
||||
ob << false;
|
||||
} else {
|
||||
@@ -205,9 +203,11 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl<PType> {
|
||||
ob << scales;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
bool has_attrs;
|
||||
ib >> has_attrs;
|
||||
|
||||
@@ -360,6 +360,7 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl<PType> {
|
||||
|
||||
_engine = &ib.get_engine();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -424,22 +425,6 @@ private:
|
||||
protected:
|
||||
virtual bool optimized_out(typed_primitive_inst<PType>&) const { return false; }
|
||||
|
||||
static bool has_output_scales(const std::shared_ptr<dnnl::primitive_attr>& attr) {
|
||||
int mask;
|
||||
std::vector<float> scales;
|
||||
attr->get_output_scales(mask, scales);
|
||||
const auto drfv = reinterpret_cast<const int32_t&>(DNNL_RUNTIME_F32_VAL);
|
||||
return !scales.empty() && (reinterpret_cast<const int32_t&>(scales[0]) == drfv);
|
||||
}
|
||||
|
||||
static bool has_zero_points(int arg, const std::shared_ptr<dnnl::primitive_attr>& attr) {
|
||||
int mask;
|
||||
std::vector<int32_t> zp;
|
||||
attr->get_zero_points(arg, mask, zp);
|
||||
const auto drsv = reinterpret_cast<const int32_t&>(DNNL_RUNTIME_S32_VAL);
|
||||
return !zp.empty() && (reinterpret_cast<const int32_t&>(zp[0]) == drsv);
|
||||
}
|
||||
|
||||
void configure_post_ops_arguments(typed_primitive_inst<PType>& instance, std::unordered_map<int, dnnl::memory>& args) const {
|
||||
auto& engine = instance.get_network().get_engine();
|
||||
auto dnnl_engine = engine.get_onednn_engine();
|
||||
@@ -453,7 +438,7 @@ protected:
|
||||
for (size_t post_op_idx = 0, num_of_optimized_post_ops = 0; post_op_idx < post_ops_size; post_op_idx++) {
|
||||
auto post_op_type = cur_post_ops[post_op_idx].op_type;
|
||||
auto memory_offset = cur_post_ops[post_op_idx].mem_offset;
|
||||
auto onednn_post_op_idx = has_output_scales(_attrs) && post_op_idx > 0 ? post_op_idx - 1 : post_op_idx;
|
||||
auto onednn_post_op_idx = post_op_idx;
|
||||
onednn_post_op_idx -= num_of_optimized_post_ops;
|
||||
|
||||
switch (post_op_type) {
|
||||
@@ -489,14 +474,6 @@ protected:
|
||||
break;
|
||||
}
|
||||
|
||||
case onednn_post_op_type::scale:
|
||||
{
|
||||
auto scale_op_mem = instance.fused_memory(memory_offset);
|
||||
dnnl::memory::desc desc = onednn::layout_to_memory_desc(scale_op_mem->get_layout(), dnnl::memory::format_tag::a, true);
|
||||
args.insert({DNNL_ARG_ATTR_OUTPUT_SCALES, scale_op_mem->get_onednn_memory(desc)});
|
||||
break;
|
||||
}
|
||||
|
||||
case onednn_post_op_type::sum:
|
||||
case onednn_post_op_type::optimized_sum:
|
||||
case onednn_post_op_type::optimized_eltwise_linear:
|
||||
|
||||
@@ -37,8 +37,8 @@ static void reorder_unreduced_axis_no_fusion(const cldnn::layout& input_layout,
|
||||
output_layout.set_tensor(output_tensor);
|
||||
}
|
||||
|
||||
struct reduction_onednn : typed_primitive_onednn_impl<reduce, dnnl::reduction::desc> {
|
||||
using parent = typed_primitive_onednn_impl<reduce, dnnl::reduction::desc>;
|
||||
struct reduction_onednn : typed_primitive_onednn_impl<reduce> {
|
||||
using parent = typed_primitive_onednn_impl<reduce>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -48,7 +48,9 @@ protected:
|
||||
return make_unique<reduction_onednn>(*this);
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::reduction::desc> get_reduction_descriptor(const kernel_impl_params& impl_params) {
|
||||
static std::shared_ptr<dnnl::reduction::primitive_desc> get_reduction_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr = dnnl::primitive_attr()) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<reduce>();
|
||||
auto input_layout = impl_params.get_input_layout(0);
|
||||
auto output_layout = impl_params.get_output_layout();
|
||||
@@ -84,16 +86,19 @@ protected:
|
||||
default: throw std::runtime_error("unsupported reduce mode");
|
||||
}
|
||||
|
||||
return std::make_shared<dnnl::reduction::desc>(
|
||||
return std::make_shared<dnnl::reduction::primitive_desc>(
|
||||
engine.get_onednn_engine(),
|
||||
alg,
|
||||
input_md,
|
||||
output_md,
|
||||
p,
|
||||
eps);
|
||||
eps,
|
||||
attr);
|
||||
}
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
ob << make_data(&_desc->data, sizeof(dnnl_reduction_desc_t));
|
||||
@@ -101,9 +106,11 @@ public:
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
_desc = std::make_shared<dnnl::reduction::desc>();
|
||||
@@ -114,16 +121,16 @@ public:
|
||||
|
||||
_pd = dnnl::primitive_desc(&_desc->data, _attrs.get(), ib.get_engine().get_onednn_engine(), nullptr);
|
||||
_prim = dnnl::primitive(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const reduce_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto desc = get_reduction_descriptor(impl_params);
|
||||
auto attr = arg.get_onednn_primitive_attributes();
|
||||
dnnl::primitive_desc prim_desc{&desc->data, attr.get(), engine.get_onednn_engine(), nullptr};
|
||||
auto prim_desc = get_reduction_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
return cldnn::make_unique<reduction_onednn>(engine, config, desc, attr, prim_desc);
|
||||
return cldnn::make_unique<reduction_onednn>(engine, config, attr, *prim_desc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
struct reorder_onednn : typed_primitive_onednn_impl<reorder, void, dnnl::reorder::primitive_desc, dnnl::reorder> {
|
||||
using parent = typed_primitive_onednn_impl<reorder, void, dnnl::reorder::primitive_desc, dnnl::reorder>;
|
||||
struct reorder_onednn : typed_primitive_onednn_impl<reorder, dnnl::reorder::primitive_desc, dnnl::reorder> {
|
||||
using parent = typed_primitive_onednn_impl<reorder, dnnl::reorder::primitive_desc, dnnl::reorder>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
@@ -43,9 +43,9 @@ protected:
|
||||
return args;
|
||||
}
|
||||
|
||||
static std::shared_ptr<dnnl::reorder::primitive_desc> get_reorder_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr,
|
||||
const cldnn::engine& engine) {
|
||||
static std::shared_ptr<dnnl::reorder::primitive_desc> get_reorder_primitive_descriptor(const kernel_impl_params& impl_params,
|
||||
const dnnl::primitive_attr& attr) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto prim = impl_params.typed_desc<reorder>();
|
||||
|
||||
auto input_layout = impl_params.get_input_layout(0);
|
||||
@@ -64,14 +64,17 @@ protected:
|
||||
|
||||
public:
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::save(ob);
|
||||
|
||||
std::vector<uint8_t> prim_cache;
|
||||
prim_cache = _prim.get_cache_blob();
|
||||
ob << prim_cache;
|
||||
#endif
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
#ifdef ONEDNN_PRIMITIVE_SERIALIZATION
|
||||
parent::load(ib);
|
||||
|
||||
const kernel_impl_params* impl_params = reinterpret_cast<kernel_impl_params*>(ib.getKernlImplParams());
|
||||
@@ -82,17 +85,18 @@ public:
|
||||
ib >> prim_cache;
|
||||
|
||||
_prim = dnnl::reorder(_pd, prim_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<primitive_impl> create(const reorder_node& arg, const kernel_impl_params& impl_params) {
|
||||
auto& engine = impl_params.prog->get_engine();
|
||||
auto& config = impl_params.prog->get_config();
|
||||
auto attr = arg.get_onednn_primitive_attributes();
|
||||
auto desc = get_reorder_descriptor(impl_params, *attr, impl_params.prog->get_engine());
|
||||
auto prim_desc = get_reorder_primitive_descriptor(impl_params, *attr);
|
||||
|
||||
std::shared_ptr<void> dummy = nullptr;
|
||||
|
||||
return cldnn::make_unique<reorder_onednn>(engine, config, dummy, attr, *desc);
|
||||
return cldnn::make_unique<reorder_onednn>(engine, config, attr, *prim_desc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,14 +14,6 @@ namespace cldnn {
|
||||
namespace onednn {
|
||||
|
||||
namespace {
|
||||
void pad_dims(dnnl::memory::dims& padded_dims, cldnn::format format) {
|
||||
auto block_sizes = format.block_sizes();
|
||||
for (auto& block : block_sizes) {
|
||||
auto rounded_dim = round_up_to(padded_dims[block.first], block.second);
|
||||
padded_dims[block.first] = rounded_dim;
|
||||
}
|
||||
}
|
||||
|
||||
std::string convert_data_format_string(cldnn::format fmt) {
|
||||
switch (fmt) {
|
||||
case cldnn::format::b_fs_yx_fsv2: return "aBcd2b";
|
||||
@@ -36,78 +28,6 @@ std::string convert_data_format_string(cldnn::format fmt) {
|
||||
}
|
||||
}
|
||||
|
||||
dnnl::memory::desc create_memory_desc_from_format_string(dnnl::memory::dims dims, dnnl::memory::data_type dt, std::string tag) {
|
||||
dnnl::memory::desc desc;
|
||||
dnnl_memory_desc_t* md = &desc.data;
|
||||
|
||||
int ndims = static_cast<int>(dims.size());
|
||||
md->ndims = ndims;
|
||||
if (ndims > DNNL_MAX_NDIMS) throw std::invalid_argument("[clDNN] Unsupported ndims " + std::to_string(ndims));
|
||||
|
||||
std::copy(&dims[0], &dims[0] + ndims, md->dims);
|
||||
md->data_type = static_cast<dnnl_data_type_t>(dt);
|
||||
md->format_kind = dnnl_blocked;
|
||||
|
||||
// Parse dimensions and their block sizes starting from the innermost one.
|
||||
std::vector<std::pair<int, int>> dim_blocks;
|
||||
int pos = static_cast<int>(tag.size()) - 1;
|
||||
int ndims_from_tag = -1;
|
||||
while (pos >= 0) {
|
||||
int pos0 = pos;
|
||||
|
||||
--pos;
|
||||
while (pos >= 0 && std::isdigit(tag[pos]))
|
||||
pos--;
|
||||
|
||||
int dim_idx = std::tolower(tag[pos0]) - 'a';
|
||||
if (dim_idx >= ndims) throw std::invalid_argument("[clDNN] Unsupported tag for oneDNN " + tag);
|
||||
ndims_from_tag = std::max(dim_idx + 1, ndims_from_tag);
|
||||
int block_str_len = pos0 - pos - 1;
|
||||
int block = (block_str_len == 0)
|
||||
? 1
|
||||
: std::stoi(tag.substr(pos + 1, block_str_len));
|
||||
dim_blocks.emplace_back(dim_idx, block);
|
||||
}
|
||||
if (ndims_from_tag != ndims) throw std::invalid_argument("[clDNN] Unsupported tag for oneDNN " + tag);
|
||||
|
||||
auto &blk = md->format_desc.blocking;
|
||||
|
||||
// Compute strides and fill inner block sizes/indices.
|
||||
dnnl_dim_t stride = 1;
|
||||
dnnl_dims_t full_inner_blks;
|
||||
std::fill(full_inner_blks, full_inner_blks + md->ndims, 1);
|
||||
for (auto &p : dim_blocks) {
|
||||
int dim_idx = p.first;
|
||||
int block = p.second;
|
||||
if (block == 1) {
|
||||
assert(blk.strides[dim_idx] == 0);
|
||||
blk.strides[dim_idx] = stride;
|
||||
|
||||
dnnl_dim_t fib = full_inner_blks[dim_idx];
|
||||
dnnl_dim_t padded_dim = md->dims[dim_idx] == DNNL_RUNTIME_DIM_VAL
|
||||
? DNNL_RUNTIME_DIM_VAL
|
||||
: (md->dims[dim_idx] + fib - 1) / fib * fib;
|
||||
md->padded_dims[dim_idx] = padded_dim;
|
||||
if (padded_dim == DNNL_RUNTIME_DIM_VAL)
|
||||
stride = DNNL_RUNTIME_DIM_VAL;
|
||||
else
|
||||
stride *= (padded_dim / fib);
|
||||
} else {
|
||||
full_inner_blks[dim_idx] *= block;
|
||||
blk.inner_blks[blk.inner_nblks] = block;
|
||||
blk.inner_idxs[blk.inner_nblks] = dim_idx;
|
||||
blk.inner_nblks++;
|
||||
stride *= block;
|
||||
}
|
||||
}
|
||||
|
||||
// Inner block sizes/indices are stored from the outermost to the innermost
|
||||
// so need to reverse them.
|
||||
std::reverse(blk.inner_blks, blk.inner_blks + blk.inner_nblks);
|
||||
std::reverse(blk.inner_idxs, blk.inner_idxs + blk.inner_nblks);
|
||||
|
||||
return desc;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename T>
|
||||
@@ -204,6 +124,7 @@ std::vector<std::pair<cldnn::format, dnnl::memory::format_tag>> format_map = {
|
||||
{ cldnn::format::b_fs_zyx_fsv16, dnnl::memory::format_tag::nCdhw16c },
|
||||
{ cldnn::format::b_fs_zyx_fsv32, dnnl::memory::format_tag::aBcde32b },
|
||||
{ cldnn::format::bs_fs_yx_bsv16_fsv16, dnnl::memory::format_tag::NChw16n16c },
|
||||
{ cldnn::format::bs_fs_yx_bsv16_fsv32, dnnl::memory::format_tag::NChw16n32c },
|
||||
{ cldnn::format::bs_fs_yx_bsv32_fsv32, dnnl::memory::format_tag::NChw32n32c },
|
||||
{ cldnn::format::bs_fs_yx_bsv4_fsv4, dnnl::memory::format_tag::ABcd4a4b },
|
||||
{ cldnn::format::bs_fs_yx_bsv8_fsv4, dnnl::memory::format_tag::ABcd8a4b },
|
||||
@@ -213,6 +134,7 @@ std::vector<std::pair<cldnn::format, dnnl::memory::format_tag>> format_map = {
|
||||
{ cldnn::format::bs_fs_zyx_bsv32_fsv16, dnnl::memory::format_tag::NCdhw32n16c },
|
||||
{ cldnn::format::bs_fs_zyx_bsv32_fsv32, dnnl::memory::format_tag::NCdhw32n32c },
|
||||
{ cldnn::format::bs_fs_zyx_bsv16_fsv16, dnnl::memory::format_tag::NCdhw16n16c },
|
||||
// { cldnn::format::bs_fs_zyx_bsv16_fsv32, dnnl::memory::format_tag::NCdhw16n32c }, // TODO onednn3.0: Request NCdhw16n32c format
|
||||
{ cldnn::format::bs_fs_zyx_bsv8_fsv4, dnnl::memory::format_tag::ABcde8a4b },
|
||||
{ cldnn::format::bs_fs_zyx_bsv8_fsv2, dnnl::memory::format_tag::ABcde8a2b },
|
||||
};
|
||||
@@ -260,55 +182,48 @@ int64_t get_f_offset(cldnn::layout&& l, dnnl::memory::desc&& desc) {
|
||||
}
|
||||
}
|
||||
|
||||
switch (desc.data.data_type) {
|
||||
case dnnl_data_type_t::dnnl_s8:
|
||||
case dnnl_data_type_t::dnnl_u8:
|
||||
switch (desc.get_data_type()) {
|
||||
case dnnl::memory::data_type::s8:
|
||||
case dnnl::memory::data_type::u8:
|
||||
return offset;
|
||||
case dnnl_data_type_t::dnnl_f16:
|
||||
case dnnl_data_type_t::dnnl_bf16:
|
||||
case dnnl::memory::data_type::f16:
|
||||
case dnnl::memory::data_type::bf16:
|
||||
return (offset * 2);
|
||||
case dnnl_data_type_t::dnnl_f32:
|
||||
case dnnl_data_type_t::dnnl_s32:
|
||||
case dnnl::memory::data_type::f32:
|
||||
case dnnl::memory::data_type::s32:
|
||||
return (offset * 4);
|
||||
default: throw std::runtime_error(std::string("Unsupported offset for dnnl_data_type_t ") + dnnl_dt2str(desc.data.data_type));
|
||||
default:
|
||||
throw std::runtime_error(std::string("Unsupported offset for dnnl_data_type_t ")
|
||||
+ dnnl_dt2str(static_cast<dnnl_data_type_t>(desc.get_data_type())));
|
||||
}
|
||||
}
|
||||
|
||||
dnnl::memory::desc layout_to_memory_desc(cldnn::layout l, dnnl::memory::format_tag target_fmt, bool flatten) {
|
||||
dnnl::memory::dims dims;
|
||||
dnnl::memory::dims padded_dims;
|
||||
dnnl::memory::dims padded_offset;
|
||||
if (target_fmt == dnnl::memory::format_tag::ab && flatten) {
|
||||
dims = flatten_tensor(l.get_tensor());
|
||||
dims.insert(dims.begin(), 1);
|
||||
} else if (target_fmt == dnnl::memory::format_tag::ab) {
|
||||
dims.push_back(l.batch());
|
||||
dims.push_back(l.get_tensor().count() / l.batch());
|
||||
padded_dims = dims;
|
||||
} else if (flatten) {
|
||||
dims = flatten_tensor(l.get_tensor());
|
||||
} else {
|
||||
auto rank = cldnn::format::dimension(l.format);
|
||||
dims = convert_tensor(l.get_tensor(), rank, cldnn::format::is_grouped(l.format));
|
||||
}
|
||||
padded_dims = dims;
|
||||
pad_dims(padded_dims, l.format);
|
||||
|
||||
dnnl::memory::data_type dt = convert_data_type(l.data_type);
|
||||
dnnl::memory::format_tag fmt = target_fmt == dnnl::memory::format_tag::undef ? convert_data_format(l.format) : target_fmt;
|
||||
|
||||
if (fmt == dnnl::memory::format_tag::undef) {
|
||||
return create_memory_desc_from_format_string(dims, dt, convert_data_format_string(l.format));
|
||||
throw ov::Exception("[GPU] Unexpected fmt: " + convert_data_format_string(l.format));
|
||||
} else {
|
||||
dnnl::memory::desc res(dims, dt, fmt);
|
||||
|
||||
std::copy(padded_dims.begin(), padded_dims.end(), res.data.padded_dims);
|
||||
std::copy(padded_offset.begin(), padded_offset.end(), res.data.padded_offsets);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_identical_order(std::vector<std::vector<size_t>>& orders, std::vector<size_t> order,
|
||||
size_t first, size_t depth) {
|
||||
if (depth == 0)
|
||||
@@ -323,12 +238,11 @@ static void get_identical_order(std::vector<std::vector<size_t>>& orders, std::v
|
||||
std::swap(order[first], order[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// Get candidate orders calculated by stride value of dnnl::memory::descriptor could be multiple
|
||||
std::vector<std::vector<size_t>> get_candidate_orders(dnnl::memory::desc desc) {
|
||||
std::vector<std::vector<size_t>> orders;
|
||||
auto strides = desc.data.format_desc.blocking.strides;
|
||||
std::vector<size_t> order(desc.data.ndims);
|
||||
auto strides = desc.get_strides();
|
||||
std::vector<size_t> order(desc.get_ndims());
|
||||
std::iota(order.begin(), order.end(), 0);
|
||||
std::sort(order.begin(), order.end(),
|
||||
[&strides] (size_t ind_l, size_t ind_r) {
|
||||
@@ -367,18 +281,17 @@ static bool compare_orders(std::vector<std::vector<size_t>> a, std::vector<size_
|
||||
}
|
||||
|
||||
cldnn::format find_data_format(dnnl::memory::desc desc) {
|
||||
auto blk = desc.data.format_desc.blocking;
|
||||
auto order = get_candidate_orders(desc);
|
||||
|
||||
for (int32_t fmt_idx = format::bfyx ; fmt_idx < format::oiyx ; fmt_idx++) {
|
||||
auto candidate_trait = format::traits(static_cast<format::type>(fmt_idx));
|
||||
if (desc.data.ndims == static_cast<int>(candidate_trait._order.size())
|
||||
&& blk.inner_nblks == static_cast<int>(candidate_trait.block_sizes.size())
|
||||
if (desc.get_ndims() == static_cast<int>(candidate_trait._order.size())
|
||||
&& desc.get_inner_nblks() == static_cast<int>(candidate_trait.block_sizes.size())
|
||||
&& compare_orders(order, candidate_trait._order)) {
|
||||
bool is_match = true;
|
||||
for (size_t idx = 0 ; idx < candidate_trait.block_sizes.size() ; idx++) {
|
||||
if (blk.inner_blks[idx] != static_cast<int>(candidate_trait.block_sizes[idx].second)
|
||||
|| blk.inner_idxs[idx] != static_cast<int>(candidate_trait.block_sizes[idx].first)) {
|
||||
if (desc.get_inner_blks()[idx] != static_cast<int>(candidate_trait.block_sizes[idx].second)
|
||||
|| desc.get_inner_idxs()[idx] != static_cast<int>(candidate_trait.block_sizes[idx].first)) {
|
||||
is_match = false;
|
||||
break;
|
||||
}
|
||||
@@ -390,17 +303,16 @@ cldnn::format find_data_format(dnnl::memory::desc desc) {
|
||||
|
||||
std::stringstream msg;
|
||||
msg << "Unsupported onednn dnnl::memory::desc find_data_format. "
|
||||
<< "ndims: " << desc.data.ndims
|
||||
<< ", inner_nblks: " << blk.inner_nblks
|
||||
<< "ndims: " << desc.get_ndims()
|
||||
<< ", inner_nblks: " << desc.get_inner_nblks()
|
||||
<< ", inner_blks: ";
|
||||
for (int i = 0; i < blk.inner_nblks; i++)
|
||||
msg << "(blk " << blk.inner_blks[i] << ", idx " << blk.inner_idxs[i] << ") ";
|
||||
for (int i = 0; i < desc.get_inner_nblks(); i++)
|
||||
msg << "(blk " << desc.get_inner_blks()[i] << ", idx " << desc.get_inner_idxs()[i] << ") ";
|
||||
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
|
||||
cldnn::format find_format(dnnl::memory::desc desc, bool is_grouped) {
|
||||
auto blk = desc.data.format_desc.blocking;
|
||||
auto orders = get_candidate_orders(desc);
|
||||
|
||||
format start_format = format::oiyx;
|
||||
@@ -409,8 +321,8 @@ cldnn::format find_format(dnnl::memory::desc desc, bool is_grouped) {
|
||||
|
||||
for (int32_t fmt_idx = start_format ; fmt_idx < format::format_num ; fmt_idx++) {
|
||||
auto candidate_trait = format::traits(static_cast<format::type>(fmt_idx));
|
||||
if (static_cast<size_t>(desc.data.ndims) == candidate_trait._order.size()
|
||||
&& static_cast<size_t>(blk.inner_nblks) == candidate_trait.block_sizes.size()
|
||||
if (static_cast<size_t>(desc.get_ndims()) == candidate_trait._order.size()
|
||||
&& static_cast<size_t>(desc.get_inner_nblks()) == candidate_trait.block_sizes.size()
|
||||
&& compare_orders(orders, candidate_trait._order)) {
|
||||
// Compare all pairs of dimension number and block size to format_traits_map of all formats
|
||||
bool is_match = true;
|
||||
@@ -420,21 +332,21 @@ cldnn::format find_format(dnnl::memory::desc desc, bool is_grouped) {
|
||||
if (is_grouped && candidate_trait.is_group_char(candidate_trait.internal_order[block_idx])) {
|
||||
// inner_idx gets the index of group dimension in mem::desc when blocked axis is group
|
||||
auto inner_idx = candidate_trait.order.find_first_of(candidate_trait.internal_order[block_idx]);
|
||||
if (blk.inner_blks[idx] != block_size ||
|
||||
blk.inner_idxs[idx] != static_cast<dnnl_dim_t>(inner_idx)) {
|
||||
if (desc.get_inner_blks()[idx] != block_size ||
|
||||
desc.get_inner_idxs()[idx] != static_cast<dnnl_dim_t>(inner_idx)) {
|
||||
is_match = false;
|
||||
break;
|
||||
}
|
||||
} else if (is_grouped) {
|
||||
// g,o,i from cldnn formats are matching to a,b,c of dnnl. But g is at the end of internal order.
|
||||
if (blk.inner_blks[idx] != block_size ||
|
||||
(blk.inner_idxs[idx] - static_cast<dnnl_dim_t>(candidate_trait.group_num)) != block_idx) {
|
||||
if (desc.get_inner_blks()[idx] != block_size ||
|
||||
(desc.get_inner_idxs()[idx] - static_cast<dnnl_dim_t>(candidate_trait.group_num)) != block_idx) {
|
||||
is_match = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (blk.inner_blks[idx] != block_size ||
|
||||
blk.inner_idxs[idx] != block_idx) {
|
||||
if (desc.get_inner_blks()[idx] != block_size ||
|
||||
desc.get_inner_idxs()[idx] != block_idx) {
|
||||
is_match = false;
|
||||
break;
|
||||
}
|
||||
@@ -448,18 +360,19 @@ cldnn::format find_format(dnnl::memory::desc desc, bool is_grouped) {
|
||||
|
||||
std::stringstream msg;
|
||||
msg << "Unsupported " << (is_grouped ? "grouped" : "") << "onednn dnnl::memory::desc find_format. "
|
||||
<< "ndims: " << desc.data.ndims
|
||||
<< ", inner_nblks: " << blk.inner_nblks
|
||||
<< "ndims: " << desc.get_ndims()
|
||||
<< ", inner_nblks: " << desc.get_inner_nblks()
|
||||
<< ", inner_blks: ";
|
||||
for (int i = 0; i < blk.inner_nblks; i++)
|
||||
msg << "(blk " << blk.inner_blks[i] << ", idx " << blk.inner_idxs[i] << ") ";
|
||||
for (int i = 0; i < desc.get_inner_nblks(); i++)
|
||||
msg << "(blk " << desc.get_inner_blks()[i] << ", idx " << desc.get_inner_idxs()[i] << ") ";
|
||||
for (auto order : orders) {
|
||||
msg << ", strides_order : ";
|
||||
|
||||
for (const auto& value : order)
|
||||
msg << value << " ";
|
||||
}
|
||||
msg << ", stride_value : ";
|
||||
auto strides = desc.data.format_desc.blocking.strides;
|
||||
auto strides = desc.get_strides();
|
||||
for (size_t idx = 0; idx < orders[0].size() ; idx++) {
|
||||
msg << strides[idx] << " ";
|
||||
}
|
||||
@@ -472,7 +385,7 @@ dnnl::algorithm convert_activation_func(cldnn::activation_func func) {
|
||||
switch (func) {
|
||||
case cldnn::activation_func::relu: return dnnl::algorithm::eltwise_relu;
|
||||
case cldnn::activation_func::relu_negative_slope: return dnnl::algorithm::eltwise_relu;
|
||||
case cldnn::activation_func::gelu: return dnnl::algorithm::eltwise_gelu;
|
||||
case cldnn::activation_func::gelu: return dnnl::algorithm::eltwise_gelu_erf;
|
||||
case cldnn::activation_func::elu: return dnnl::algorithm::eltwise_elu;
|
||||
case cldnn::activation_func::mish: return dnnl::algorithm::eltwise_mish;
|
||||
case cldnn::activation_func::swish: return dnnl::algorithm::eltwise_swish;
|
||||
@@ -510,5 +423,6 @@ bool is_per_tensor(cldnn::data_node& node, int32_t& zp_val) {
|
||||
|
||||
template bool is_per_tensor<int8_t>(cldnn::data_node& node, int32_t& zp_val);
|
||||
template bool is_per_tensor<uint8_t>(cldnn::data_node& node, int32_t& zp_val);
|
||||
|
||||
} // namespace onednn
|
||||
} // namespace cldnn
|
||||
@@ -465,8 +465,8 @@ private:
|
||||
onednn_attrs = attrs;
|
||||
}
|
||||
|
||||
bool has_out_scales(const std::shared_ptr<dnnl::primitive_attr>& attr);
|
||||
dnnl::post_ops try_optimize_post_ops(dnnl::post_ops& p_ops, const std::shared_ptr<dnnl::primitive_attr>& attr, bool& optimization_is_completed);
|
||||
|
||||
#endif // ENABLE_ONEDNN_FOR_GPU
|
||||
size_t num_outputs = 1;
|
||||
};
|
||||
|
||||
@@ -490,14 +490,6 @@ void program_node::set_preferred_output_fmt(size_t idx, format::type type) {
|
||||
|
||||
#ifdef ENABLE_ONEDNN_FOR_GPU
|
||||
|
||||
bool program_node::has_out_scales(const std::shared_ptr<dnnl::primitive_attr>& attr) {
|
||||
int mask;
|
||||
std::vector<float> scales;
|
||||
attr->get_output_scales(mask, scales);
|
||||
const auto drfv = reinterpret_cast<const int32_t&>(DNNL_RUNTIME_F32_VAL);
|
||||
return !scales.empty() && (reinterpret_cast<const int32_t&>(scales[0]) == drfv);
|
||||
}
|
||||
|
||||
dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const std::shared_ptr<dnnl::primitive_attr>& attr,
|
||||
bool& optimization_is_completed) {
|
||||
// Create new dnnl::post_ops object which will be filled inside the optimization process
|
||||
@@ -512,9 +504,9 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
case onednn_post_op_type::eltwise_round:
|
||||
{
|
||||
dnnl::algorithm alg;
|
||||
float scale, alpha, beta;
|
||||
cur_p_ops.get_params_eltwise(idx, scale, alg, alpha, beta);
|
||||
new_p_ops.append_eltwise(scale, alg, alpha, beta);
|
||||
float alpha, beta;
|
||||
cur_p_ops.get_params_eltwise(idx, alg, alpha, beta);
|
||||
new_p_ops.append_eltwise(alg, alpha, beta);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -551,7 +543,7 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
cur_p_ops.get_params_sum(idx, scale, data_type);
|
||||
// Only conv supports data type specification in append_sum. Other primitives(deconv, fc) do not support it.
|
||||
if (is_type<convolution>()) {
|
||||
new_p_ops.append_sum(scale, data_type);
|
||||
new_p_ops.append_sum(scale, 0/*zero_point*/, data_type);
|
||||
} else {
|
||||
new_p_ops.append_sum(scale);
|
||||
}
|
||||
@@ -604,7 +596,6 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
};
|
||||
auto type_is_binary_add = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::binary_add; };
|
||||
auto type_is_binary_mul = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::binary_mul; };
|
||||
auto type_is_sum = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::sum; };
|
||||
auto type_is_optimized_sum = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized_sum; };
|
||||
auto type_is_scale = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::scale; };
|
||||
|
||||
@@ -696,22 +687,19 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
|
||||
GPU_DEBUG_TRACE << "after prev_post_op_idx: " << prev_post_op_idx << ", cur_post_op_idx: " << cur_post_op_idx << std::endl;
|
||||
|
||||
auto cur_idx = static_cast<int>(has_out_scales(attr) ? (cur_post_op_idx >= 1 ? cur_post_op_idx - 1 : 0) : cur_post_op_idx);
|
||||
auto prev_idx = static_cast<int>(has_out_scales(attr) ? (prev_post_op_idx >= 1 ? prev_post_op_idx - 1 : 0) : prev_post_op_idx);
|
||||
|
||||
// If prev_idx and cur_idx are same, add the last post-op to dnnl::post_ops
|
||||
if (prev_post_op_idx == post_ops_size - 1 && prev_idx == cur_idx && !type_is_any_optimized(prev_type)) {
|
||||
add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx);
|
||||
// If prev_post_op_idx and cur_idx are same, add the last post-op to dnnl::post_ops
|
||||
if (prev_post_op_idx == post_ops_size - 1 && prev_post_op_idx == cur_post_op_idx && !type_is_any_optimized(prev_type)) {
|
||||
add_post_op(prev_type, p_ops, optimized_p_ops, prev_post_op_idx);
|
||||
break;
|
||||
}
|
||||
|
||||
// If this is the last pair and it's optimized - add the last post-op and go out from the cycle
|
||||
if (cur_post_op_idx == post_ops_size - 1 && (type_is_any_optimized(cur_type) || type_is_any_optimized(prev_type))) {
|
||||
if (!type_is_any_optimized(prev_type)) {
|
||||
add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx);
|
||||
add_post_op(prev_type, p_ops, optimized_p_ops, prev_post_op_idx);
|
||||
}
|
||||
if (!type_is_any_optimized(cur_type)) {
|
||||
add_post_op(cur_type, p_ops, optimized_p_ops, cur_idx);
|
||||
add_post_op(cur_type, p_ops, optimized_p_ops, cur_post_op_idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -720,50 +708,35 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
auto eltw_and_eltw = type_is_eltwise(cur_type) && type_is_eltwise(prev_type);
|
||||
auto bin_and_eltw = type_is_binary_add_or_mul(cur_type) && type_is_eltwise_linear(prev_type);
|
||||
auto eltw_and_bin = type_is_eltwise_linear(cur_type) && type_is_binary_add_or_mul(prev_type);
|
||||
auto sum_and_eltw = type_is_sum(cur_type) && type_is_eltwise(prev_type);
|
||||
auto eltw_and_scale = type_is_eltwise_linear(cur_type) && type_is_scale(prev_type);
|
||||
|
||||
auto can_try_optimize = eltw_and_eltw ||
|
||||
bin_and_eltw ||
|
||||
eltw_and_bin ||
|
||||
sum_and_eltw ||
|
||||
eltw_and_scale;
|
||||
|
||||
bool cur_ops_pair_is_optimized = false;
|
||||
|
||||
GPU_DEBUG_TRACE << "prev_idx: " << prev_idx << " " << prev_type
|
||||
<< ", cur_idx: " << cur_idx << " " << cur_type << std::endl;
|
||||
|
||||
if (can_try_optimize) {
|
||||
if (eltw_and_eltw) {
|
||||
dnnl::algorithm cur_alg, prev_alg;
|
||||
float cur_scale, prev_scale, cur_alpha, prev_alpha, cur_beta, prev_beta;
|
||||
float cur_alpha, prev_alpha, cur_beta, prev_beta;
|
||||
|
||||
p_ops.get_params_eltwise(prev_idx, prev_scale, prev_alg, prev_alpha, prev_beta);
|
||||
p_ops.get_params_eltwise(cur_idx, cur_scale, cur_alg, cur_alpha, cur_beta);
|
||||
p_ops.get_params_eltwise(prev_post_op_idx, prev_alg, prev_alpha, prev_beta);
|
||||
p_ops.get_params_eltwise(cur_post_op_idx, cur_alg, cur_alpha, cur_beta);
|
||||
|
||||
auto eltw_linear_and_eltw_linear = type_is_eltwise_linear(cur_type) && type_is_eltwise_linear(prev_type);
|
||||
auto eltw_linear_and_eltw_non_linear = type_is_eltwise_linear(cur_type) && !type_is_eltwise_linear(prev_type) && cur_beta == 0;
|
||||
|
||||
// eltwise_linear + eltwise_linear combination can be optimized always
|
||||
if (eltw_linear_and_eltw_linear) {
|
||||
dnnl::post_ops eltw_p_op;
|
||||
float optimized_alpha = cur_alpha * prev_alpha * prev_scale;
|
||||
float optimized_beta = cur_alpha * prev_beta * prev_scale + cur_beta;
|
||||
float optimized_scale = cur_scale;
|
||||
eltw_p_op.append_eltwise(optimized_scale, cur_alg, optimized_alpha, optimized_beta);
|
||||
float optimized_alpha = cur_alpha * prev_alpha;
|
||||
float optimized_beta = cur_alpha * prev_beta + cur_beta;
|
||||
eltw_p_op.append_eltwise(cur_alg, optimized_alpha, optimized_beta);
|
||||
|
||||
// Combine 2 eltwises into one
|
||||
add_post_op(cur_type, eltw_p_op, optimized_p_ops, 0);
|
||||
} else if (eltw_linear_and_eltw_non_linear) {
|
||||
dnnl::post_ops eltw_p_op;
|
||||
eltw_p_op.append_eltwise(cur_scale * prev_scale * cur_alpha, prev_alg, prev_alpha, prev_beta);
|
||||
|
||||
// Combine 2 eltwises into one
|
||||
add_post_op(prev_type, eltw_p_op, optimized_p_ops, 0);
|
||||
}
|
||||
|
||||
if (eltw_linear_and_eltw_linear || eltw_linear_and_eltw_non_linear) {
|
||||
// Marked current and previous eltwise operations as 'optimized' (they will be ignored on the next iteration of cycle)
|
||||
cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized;
|
||||
cur_post_ops[prev_post_op_idx].op_type = get_optimized_eltwise_type(prev_type);
|
||||
@@ -782,18 +755,18 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
} else if (bin_and_eltw) {
|
||||
dnnl::algorithm alg;
|
||||
dnnl::memory::desc desc;
|
||||
float scale, alpha, beta;
|
||||
float alpha, beta;
|
||||
|
||||
cldnn::program_node& cur_node = get_dependency(cur_post_ops[cur_post_op_idx].mem_dep);
|
||||
|
||||
p_ops.get_params_binary(cur_idx, alg, desc);
|
||||
p_ops.get_params_eltwise(prev_idx, scale, alg, alpha, beta);
|
||||
p_ops.get_params_binary(cur_post_op_idx, alg, desc);
|
||||
p_ops.get_params_eltwise(prev_post_op_idx, alg, alpha, beta);
|
||||
|
||||
// Eltwise operations can use runtime non-constant data buffers, so check that memory buffers consist of constant data only
|
||||
auto bin_ops_can_be_optimized = cur_node.is_type<data>() && cur_node.is_constant() &&
|
||||
cur_node.get_users().size() == 1 && desc.data_type() == dnnl_f32;
|
||||
cur_node.get_users().size() == 1 && desc.get_data_type() == dnnl_f32;
|
||||
|
||||
auto bin_add_and_eltw = alpha == 1.0f && scale == 1.0f && type_is_binary_add(cur_type) && bin_ops_can_be_optimized;
|
||||
auto bin_add_and_eltw = alpha == 1.0f && type_is_binary_add(cur_type) && bin_ops_can_be_optimized;
|
||||
auto bin_mul_and_eltw = beta == 0.f && type_is_binary_mul(cur_type) && bin_ops_can_be_optimized;
|
||||
|
||||
if (bin_add_and_eltw || bin_mul_and_eltw) {
|
||||
@@ -812,7 +785,7 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
}
|
||||
} else {
|
||||
for (size_t data_idx = 0; data_idx < cur_bin_mem_size; data_idx++) {
|
||||
bin_and_eltw_lock[data_idx] *= alpha * scale;
|
||||
bin_and_eltw_lock[data_idx] *= alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,18 +797,18 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
} else if (eltw_and_bin) {
|
||||
dnnl::algorithm alg;
|
||||
dnnl::memory::desc desc;
|
||||
float scale, alpha, beta;
|
||||
float alpha, beta;
|
||||
|
||||
cldnn::program_node& prev_node = get_dependency(cur_post_ops[prev_post_op_idx].mem_dep);
|
||||
|
||||
p_ops.get_params_eltwise(cur_idx, scale, alg, alpha, beta);
|
||||
p_ops.get_params_binary(prev_idx, alg, desc);
|
||||
p_ops.get_params_eltwise(cur_post_op_idx, alg, alpha, beta);
|
||||
p_ops.get_params_binary(prev_post_op_idx, alg, desc);
|
||||
|
||||
// Eltwise operations can use runtime non-constant data buffers, so check that memory buffers consist of constant data only
|
||||
auto bin_ops_can_be_optimized = prev_node.is_type<data>() && prev_node.is_constant() &&
|
||||
prev_node.get_users().size() == 1 && desc.data_type() == dnnl_f32;
|
||||
prev_node.get_users().size() == 1 && desc.get_data_type() == dnnl_f32;
|
||||
|
||||
auto eltw_and_bin_add = alpha == 1.0f && scale == 1.0f && type_is_binary_add(prev_type) && bin_ops_can_be_optimized;
|
||||
auto eltw_and_bin_add = alpha == 1.0f && type_is_binary_add(prev_type) && bin_ops_can_be_optimized;
|
||||
auto eltw_and_bin_mul = beta == 0.f && type_is_binary_mul(prev_type) && bin_ops_can_be_optimized;
|
||||
|
||||
if (eltw_and_bin_add || eltw_and_bin_mul) {
|
||||
@@ -854,76 +827,22 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
}
|
||||
} else {
|
||||
for (size_t data_idx = 0; data_idx < prev_bin_mem_size; data_idx++) {
|
||||
eltw_and_bin_lock[data_idx] *= alpha * scale;
|
||||
eltw_and_bin_lock[data_idx] *= alpha;
|
||||
}
|
||||
}
|
||||
|
||||
// Marked current eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle)
|
||||
cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized;
|
||||
|
||||
cur_ops_pair_is_optimized = true;
|
||||
}
|
||||
} else if (sum_and_eltw) {
|
||||
dnnl::algorithm alg;
|
||||
float sum_scale, eltw_scale, alpha, beta;
|
||||
|
||||
dnnl::algorithm next_alg;
|
||||
float next_scale, next_alpha, next_beta;
|
||||
int64_t next_idx = cur_idx + 1;
|
||||
int64_t next_post_op_idx = cur_post_op_idx + 1;
|
||||
|
||||
bool can_optimize_eltw_and_sum = false;
|
||||
|
||||
if (cur_post_op_idx < post_ops_size - 1) {
|
||||
auto next_type = cur_post_ops[next_post_op_idx].op_type;
|
||||
if (type_is_eltwise_linear(next_type)) {
|
||||
p_ops.get_params_eltwise(next_idx, next_scale, next_alg, next_alpha, next_beta);
|
||||
|
||||
if (next_beta == 0)
|
||||
can_optimize_eltw_and_sum = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to optimize eltwise (any) + sum + eltwise_linear (with beta = 0) chain of operations
|
||||
if (can_optimize_eltw_and_sum) {
|
||||
dnnl::memory::data_type data_type;
|
||||
p_ops.get_params_sum(cur_idx, sum_scale, data_type);
|
||||
p_ops.get_params_eltwise(prev_idx, eltw_scale, alg, alpha, beta);
|
||||
|
||||
dnnl::post_ops eltw_p_op_prev, sum_p_op;
|
||||
|
||||
eltw_p_op_prev.append_eltwise(eltw_scale * next_alpha * next_scale, alg, alpha, beta);
|
||||
// Only conv supports data type specification in append_sum. Other primitives(deconv, fc) do not support it.
|
||||
if (is_type<convolution>()) {
|
||||
sum_p_op.append_sum(sum_scale * next_alpha, data_type);
|
||||
} else {
|
||||
sum_p_op.append_sum(sum_scale * next_alpha);
|
||||
}
|
||||
add_post_op(prev_type, eltw_p_op_prev, optimized_p_ops, 0);
|
||||
add_post_op(cur_type, sum_p_op, optimized_p_ops, 0);
|
||||
|
||||
// Marked current, previous and next operations as 'optimized' (they will be ignored on the next iteration of cycle)
|
||||
cur_post_ops[prev_post_op_idx].op_type = get_optimized_eltwise_type(prev_type);
|
||||
cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized_sum;
|
||||
cur_post_ops[next_post_op_idx].op_type = onednn_post_op_type::optimized;
|
||||
|
||||
// Set the flag if extra optimizations checking is needed
|
||||
if (next_post_op_idx < post_ops_size - 1) {
|
||||
if (type_is_eltwise_linear(cur_post_ops[next_post_op_idx + 1].op_type) ||
|
||||
type_is_optimized_eltwise(cur_post_ops[next_post_op_idx + 1].op_type)) {
|
||||
optimization_is_completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
cur_ops_pair_is_optimized = true;
|
||||
}
|
||||
} else if (eltw_and_scale) {
|
||||
dnnl::algorithm alg;
|
||||
float eltw_scale, alpha, beta;
|
||||
float alpha, beta;
|
||||
|
||||
cldnn::program_node& prev_node = get_dependency(cur_post_ops[prev_post_op_idx].mem_dep);
|
||||
|
||||
p_ops.get_params_eltwise(cur_idx, eltw_scale, alg, alpha, beta);
|
||||
p_ops.get_params_eltwise(cur_post_op_idx, alg, alpha, beta);
|
||||
|
||||
// Eltwise can be inserted into the output_scale if cur_beta is equal to 0.f
|
||||
if (beta == 0.f && prev_node.get_output_layout().data_type == data_types::f32) {
|
||||
@@ -937,7 +856,7 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
|
||||
// Update all scale coefficients
|
||||
for (size_t data_idx = 0; data_idx < prev_scale_mem_size; data_idx++) {
|
||||
eltw_and_scale_lock[data_idx] *= alpha * eltw_scale;
|
||||
eltw_and_scale_lock[data_idx] *= alpha;
|
||||
}
|
||||
|
||||
// Marked current eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle)
|
||||
@@ -949,14 +868,14 @@ dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const
|
||||
}
|
||||
|
||||
// If no optimizations have been applied then copy post-op info into the new optimized_p_ops structure
|
||||
if (!(has_out_scales(attr) && prev_post_op_idx == 0) && !cur_ops_pair_is_optimized) {
|
||||
add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx);
|
||||
if (!cur_ops_pair_is_optimized) {
|
||||
add_post_op(prev_type, p_ops, optimized_p_ops, prev_post_op_idx);
|
||||
}
|
||||
|
||||
if (cur_post_op_idx == post_ops_size - 1 && !cur_ops_pair_is_optimized) {
|
||||
add_post_op(cur_type, p_ops, optimized_p_ops, cur_idx);
|
||||
add_post_op(cur_type, p_ops, optimized_p_ops, cur_post_op_idx);
|
||||
optimization_done = true;
|
||||
} else if (cur_post_ops[cur_post_op_idx].op_type != onednn_post_op_type::optimized) {
|
||||
} else if (cur_post_ops[cur_post_op_idx].op_type != onednn_post_op_type::optimized && cur_post_op_idx < post_ops_size - 1) {
|
||||
cur_post_op_idx++;
|
||||
prev_post_op_idx++;
|
||||
}
|
||||
@@ -1004,6 +923,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
type == onednn_post_op_type::binary_relu ||
|
||||
type == onednn_post_op_type::scale ||
|
||||
type == onednn_post_op_type::sum;
|
||||
|
||||
if (has_memory_buffers)
|
||||
memory_offset++;
|
||||
};
|
||||
@@ -1012,7 +932,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
for (size_t idx = 0; idx < cldnn_post_ops.size(); idx++) {
|
||||
auto& desc = cldnn_post_ops[idx];
|
||||
if (desc.is_type<activation>()) {
|
||||
auto fused_desc = desc.typed_desc<activation>();;
|
||||
auto fused_desc = desc.typed_desc<activation>();
|
||||
if (fused_desc->activation_function == cldnn::activation_func::relu_negative_slope
|
||||
&& !fused_desc->additional_params_input.empty()) {
|
||||
auto dep_idx = cldnn_post_ops[idx].dep_start_idx;
|
||||
@@ -1021,18 +941,20 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_relu, dep_idx);
|
||||
} else if (fused_desc->activation_function == cldnn::activation_func::hard_sigmoid) {
|
||||
// Splits hard_sigmoid activation into eltwise_linear, min and max.
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear,
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear,
|
||||
fused_desc->additional_params.a, fused_desc->additional_params.b);
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_clip, 0.0f, 1.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_clip, 0.0f, 1.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_clip, empty_mem);
|
||||
} else {
|
||||
dnnl::algorithm alg = onednn::convert_activation_func(fused_desc->activation_function);
|
||||
// Usage of alpha and beta between cldnn::pow and dnnl::eltwise::pow is different : d = pow(src, a) / d = a * pow(src, b)
|
||||
if (alg == dnnl::algorithm::eltwise_pow)
|
||||
post_ops.append_eltwise(1.0f, alg, 1.0f, fused_desc->additional_params.a);
|
||||
post_ops.append_eltwise(alg, 1.0f, fused_desc->additional_params.a);
|
||||
else if (alg == dnnl::algorithm::eltwise_hardswish) // mapping val * min(max(0, val + 3), 6) / 6 to val * max(min(1, alpha * val + beta), 0)
|
||||
post_ops.append_eltwise(alg, 1/6.f, 0.5f);
|
||||
else
|
||||
post_ops.append_eltwise(1.0f, alg, fused_desc->additional_params.a, fused_desc->additional_params.b);
|
||||
post_ops.append_eltwise(alg, fused_desc->additional_params.a, fused_desc->additional_params.b);
|
||||
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_act, empty_mem);
|
||||
}
|
||||
@@ -1044,7 +966,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
auto fusing_type = onednn_add_fusing_helpers::get_add_fusing_type(*this, cldnn_post_ops[idx]);
|
||||
if (fusing_type == add_fusing_type::sum && num_sum_post_ops == 0) {
|
||||
if (is_type<convolution>()) {
|
||||
post_ops.append_sum(1.0f, onednn::convert_data_type(in.data_type));
|
||||
post_ops.append_sum(1.0f, 0/*zero-point*/, onednn::convert_data_type(in.data_type));
|
||||
} else {
|
||||
post_ops.append_sum(1.0f);
|
||||
}
|
||||
@@ -1060,24 +982,9 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
post_ops.append_binary(dnnl::algorithm::binary_sub, in_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_sub, dep_idx);
|
||||
} else if (desc.typed_desc<eltwise>()->mode == eltwise_mode::prod) {
|
||||
auto input_datatype = get_dependency(0).get_output_layout().data_type;
|
||||
// convolution using post-op output scales can only be used when i8/u8 input (which use integer accumulator)
|
||||
bool cant_use_output_scales =
|
||||
idx != 0 ||
|
||||
has_out_scales(attrs) ||
|
||||
is_type<pooling>() ||
|
||||
is_type<reduce>() ||
|
||||
(is_type<convolution>() && data_type_traits::is_floating_point(input_datatype)) ||
|
||||
(is_type<deconvolution>() && data_type_traits::is_floating_point(input_datatype));
|
||||
if (cant_use_output_scales) {
|
||||
dnnl::memory::desc in_desc = onednn::layout_to_memory_desc(in, dnnl::memory::format_tag::ab, true);
|
||||
post_ops.append_binary(dnnl::algorithm::binary_mul, in_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx);
|
||||
} else {
|
||||
int mask = in.count() > 1 ? 2 : 0;
|
||||
attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL});
|
||||
update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx);
|
||||
}
|
||||
dnnl::memory::desc in_desc = onednn::layout_to_memory_desc(in, dnnl::memory::format_tag::ab, true);
|
||||
post_ops.append_binary(dnnl::algorithm::binary_mul, in_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx);
|
||||
} else {
|
||||
std::stringstream error_msg;
|
||||
error_msg << "Unsupported eltwise mode: " << static_cast<int>(desc.typed_desc<eltwise>()->mode) << ". ";
|
||||
@@ -1093,30 +1000,22 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
// 1. pre-scale & pre-shift
|
||||
{
|
||||
if (q_param->per_tensor_input_scale && q_param->per_tensor_input_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->in_scale, q_param->in_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->in_scale, q_param->in_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
if (q_param->per_tensor_input_scale) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->in_scale, 0.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->in_scale, 0.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto in_scale = get_dependency(dep_idx++).get_output_layout();
|
||||
if (idx == 0 && !has_out_scales(attrs) && in_scale.data_type == data_types::f32 &&
|
||||
is_type<convolution>() &&
|
||||
!data_type_traits::is_floating_point(get_dependency(0).get_output_layout().data_type)) {
|
||||
int mask = in_scale.count() > 1 ? 2 : 0;
|
||||
attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL});
|
||||
update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx - 1);
|
||||
} else {
|
||||
dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true);
|
||||
post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1);
|
||||
}
|
||||
dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true);
|
||||
post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1);
|
||||
}
|
||||
|
||||
if (q_param->has_pre_shift) {
|
||||
if (q_param->per_tensor_input_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_param->in_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, 1.0f, q_param->in_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto in_shift = get_dependency(dep_idx++).get_output_layout();
|
||||
@@ -1133,7 +1032,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
{
|
||||
bool output_type_is_int8 = out_dt == data_types::u8 || out_dt == data_types::i8;
|
||||
if (!output_type_is_int8) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_round, 0.0f, 0.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_round, 0.0f, 0.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_round, empty_mem);
|
||||
}
|
||||
}
|
||||
@@ -1142,12 +1041,12 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
{
|
||||
if (q_param->has_post_scale && q_param->has_post_shift &&
|
||||
q_param->per_tensor_output_scale && q_param->per_tensor_output_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->out_scale, q_param->out_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->out_scale, q_param->out_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
if (q_param->has_post_scale) {
|
||||
if (q_param->per_tensor_output_scale) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->out_scale, 0.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->out_scale, 0.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto out_scale = get_dependency(dep_idx++).get_output_layout();
|
||||
@@ -1159,7 +1058,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
|
||||
if (q_param->has_post_shift) {
|
||||
if (q_param->per_tensor_output_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_param->out_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, 1.0f, q_param->out_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto out_shift = get_dependency(dep_idx++).get_output_layout();
|
||||
@@ -1176,7 +1075,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
if (q_param->has_clamp || idx < cldnn_post_ops.size() - 1) {
|
||||
float out_lo = q_param->has_min_clamp ? q_param->out_lo : data_type_traits::min<float>(out_dt);
|
||||
float out_hi = q_param->has_max_clamp ? q_param->out_hi : data_type_traits::max<float>(out_dt);
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_clip, out_lo, out_hi);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_clip, out_lo, out_hi);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_clip, empty_mem);
|
||||
}
|
||||
}
|
||||
@@ -1202,30 +1101,22 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
// 2. pre-scale & pre-shift
|
||||
{
|
||||
if (q_param->per_tensor_input_scale && q_param->per_tensor_input_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->in_scale, q_param->in_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->in_scale, q_param->in_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
if (q_param->per_tensor_input_scale) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->in_scale, 0.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->in_scale, 0.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto in_scale = get_dependency(dep_idx++).get_output_layout();
|
||||
if (idx == 0 && !q_param->has_clamp && !has_out_scales(attrs) && in_scale.data_type == data_types::f32 &&
|
||||
is_type<convolution>() &&
|
||||
!data_type_traits::is_floating_point(get_dependency(0).get_output_layout().data_type)) {
|
||||
int mask = in_scale.count() > 1 ? 2 : 0;
|
||||
attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL});
|
||||
update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx - 1);
|
||||
} else {
|
||||
dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true);
|
||||
post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1);
|
||||
}
|
||||
dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true);
|
||||
post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc);
|
||||
update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1);
|
||||
}
|
||||
|
||||
if (q_param->has_pre_shift) {
|
||||
if (q_param->per_tensor_input_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_param->in_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, 1.0f, q_param->in_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto in_shift = get_dependency(dep_idx++).get_output_layout();
|
||||
@@ -1239,7 +1130,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
|
||||
// 3. round
|
||||
{
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_round, 0.0f, 0.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_round, 0.0f, 0.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_round, empty_mem);
|
||||
}
|
||||
|
||||
@@ -1247,12 +1138,12 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
{
|
||||
if (q_param->has_post_scale && q_param->has_post_shift &&
|
||||
q_param->per_tensor_output_scale && q_param->per_tensor_output_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->out_scale, q_param->out_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->out_scale, q_param->out_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
if (q_param->has_post_scale) {
|
||||
if (q_param->per_tensor_output_scale) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_param->out_scale, 0.0f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, q_param->out_scale, 0.0f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto out_scale = get_dependency(dep_idx++).get_output_layout();
|
||||
@@ -1264,7 +1155,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
|
||||
if (q_param->has_post_shift) {
|
||||
if (q_param->per_tensor_output_shift) {
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_param->out_shift);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, 1.0f, q_param->out_shift);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto out_shift = get_dependency(dep_idx++).get_output_layout();
|
||||
@@ -1290,16 +1181,16 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
auto activation_type = get_fused_activations_funcs()[i];
|
||||
if (activation_type == cldnn::activation_func::hsigmoid) {
|
||||
// Unsupported hsigmoid oneDNN gpu, splits hsigmoid activation min(max(val + 3, 0), 6) / 6
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.f, 3.f);
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_clip, 0.f, 6.f);
|
||||
post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1/6.f, 0.f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, 1.f, 3.f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_clip, 0.f, 6.f);
|
||||
post_ops.append_eltwise(dnnl::algorithm::eltwise_linear, 1/6.f, 0.f);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_clip, empty_mem);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem);
|
||||
} else {
|
||||
auto params = get_fused_activations_params()[i];
|
||||
dnnl::algorithm alg = onednn::convert_activation_func(activation_type);
|
||||
post_ops.append_eltwise(1.0f, alg, params.a, params.b);
|
||||
post_ops.append_eltwise(alg, params.a, params.b);
|
||||
update_onednn_post_op_list(onednn_post_op_type::eltwise_act, empty_mem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,46 +165,3 @@ INSTANTIATE_TEST_SUITE_P(smoke, weight_format_test_match_dnnl,
|
||||
{{32, 32, 8, 8}, dnnl::memory::data_type::u8, dnnl::memory::format_tag::BAcd4b8a8b4a, cldnn::format::is_os_yx_isa4_osa8_isv8_osv4},
|
||||
}),
|
||||
weight_format_test_match_dnnl::PrintToString);
|
||||
|
||||
struct stride_matching_test_params {
|
||||
dnnl_desc_params test_desc;
|
||||
int inner_nblks; // The number of innermost blocks
|
||||
dnnl_dims_t inner_idxs; // The size of the blocks, e.g. `{4, 16, 4}` in case of `OIhw_4i16o4i`
|
||||
dnnl_dims_t inner_blks; // The logical indices of the blocks, e.g. `{1, 0, 1}` in case of 4i16o4i
|
||||
cldnn::format cldnn_format;
|
||||
};
|
||||
|
||||
class weight_format_test_with_stride : public testing::TestWithParam<stride_matching_test_params> {
|
||||
public:
|
||||
static std::string PrintToString(testing::TestParamInfo<stride_matching_test_params> param_info) {
|
||||
auto strides = param_info.param.test_desc.strides;
|
||||
std::string res = " stride : {";
|
||||
for (auto stride : strides) {
|
||||
res += std::to_string(stride) + " ";
|
||||
}
|
||||
res += "} > " + format::traits(param_info.param.cldnn_format).str;
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(weight_format_test_with_stride, test_match_data_format) {
|
||||
auto param = GetParam();
|
||||
|
||||
dnnl::memory::desc test_desc(param.test_desc.dims, param.test_desc.data_type, param.test_desc.strides);
|
||||
test_desc.data.format_desc.blocking.inner_nblks = param.inner_nblks;
|
||||
for (auto idx = 0; idx < param.inner_nblks; idx++) {
|
||||
test_desc.data.format_desc.blocking.inner_idxs[idx] = param.inner_idxs[idx];
|
||||
test_desc.data.format_desc.blocking.inner_blks[idx] = param.inner_blks[idx];
|
||||
}
|
||||
|
||||
auto result = onednn::find_format(test_desc, false);
|
||||
ASSERT_TRUE(result == param.cldnn_format);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke, weight_format_test_with_stride,
|
||||
testing::ValuesIn(std::vector<stride_matching_test_params>{
|
||||
{{{16, 16, 1, 1}, dnnl::memory::data_type::f16, {16, 256, 1, 1}}, 2, {1, 0}, {16, 16}, cldnn::format::is_os_yx_isv16_osv16},
|
||||
{{{16, 16, 1, 1}, dnnl::memory::data_type::f16, {256, 16, 1, 1}}, 2, {1, 0}, {16, 16}, cldnn::format::os_is_yx_isv16_osv16},
|
||||
}),
|
||||
weight_format_test_with_stride::PrintToString);
|
||||
@@ -9194,6 +9194,174 @@ TEST(convolution_gpu_onednn, padding_for_cldnn_kernel_after_onednn) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(convolution_gpu_onednn, quantized_onednn_convolution_u8s8f32_asymmetric_activations_per_tensor) {
|
||||
auto& engine = get_test_engine();
|
||||
if (!engine.get_device_info().supports_immad)
|
||||
return;
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::u8, format::bfyx, { 1, 1, 5, 4 } });
|
||||
auto weights = engine.allocate_memory({ data_types::i8, format::bfyx, { 2, 1, 3, 3 } });
|
||||
auto biases = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 2, 1, 1 } });
|
||||
auto a_zp = engine.allocate_memory({ data_types::u8, format::bfyx, { 1, 1, 1, 1 } });
|
||||
|
||||
set_values<uint8_t>(input, { 1, 2, 3, 4, 5,
|
||||
2, 2, 3, 4, 6,
|
||||
3, 3, 3, 5, 1,
|
||||
1, 1, 1, 1, 1 });
|
||||
set_values<int8_t>(weights, { 1, 2, -1,
|
||||
-2, 1, 2,
|
||||
9, 7, -1,
|
||||
|
||||
9, 0, -4,
|
||||
-1, 3, 2,
|
||||
0, 2, 5 });
|
||||
set_values<uint8_t>(a_zp, { 2 });
|
||||
set_values(biases, { 1.0f, -8.0f });
|
||||
|
||||
VVVF<float> output_vec = {
|
||||
{
|
||||
{ 16.0f, 42.0f, -13.0f },
|
||||
{ 2.0f, 8.0f, 2.0f }
|
||||
},
|
||||
{
|
||||
{ -12.0f, 3.0f, 15.0f },
|
||||
{ -7.0f, 1.0f, -16.0f }
|
||||
} };
|
||||
|
||||
topology topology(
|
||||
input_layout("input", input->get_layout()),
|
||||
data("weights", weights),
|
||||
data("biases", biases),
|
||||
data("a_zp", a_zp),
|
||||
convolution("conv", input_info("input"), { "weights" }, { "biases" }, { }, { "a_zp" }, 1, data_types::f32,
|
||||
{ 2, 2 }, { 0, 0 }, { 1, 1 }, tensor{ 1, 2, 3, 2 }, false),
|
||||
reorder("out", input_info("conv"), format::bfyx, data_types::f32));
|
||||
|
||||
ExecutionConfig config;
|
||||
ov::intel_gpu::ImplementationDesc conv_impl = { format::byxf, "", impl_types::onednn };
|
||||
config.set_property(ov::intel_gpu::force_implementations(ov::intel_gpu::ImplForcingMap{ { "conv", conv_impl }}));
|
||||
config.set_property(ov::intel_gpu::optimize_data(true));
|
||||
config.set_property(ov::intel_gpu::queue_type(QueueTypes::in_order));
|
||||
|
||||
network network(engine, topology, config);
|
||||
network.set_input_data("input", input);
|
||||
|
||||
auto outputs = network.execute();
|
||||
ASSERT_EQ(outputs.begin()->first, "out");
|
||||
|
||||
auto output_memory = outputs.at("out").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output_memory, get_test_stream());
|
||||
|
||||
auto output_layout = output_memory->get_layout();
|
||||
int y_size = output_layout.spatial(1);
|
||||
int x_size = output_layout.spatial(0);
|
||||
int f_size = output_layout.feature();
|
||||
int b_size = output_layout.batch();
|
||||
ASSERT_EQ(output_layout.format, format::bfyx);
|
||||
ASSERT_EQ(y_size, 2);
|
||||
ASSERT_EQ(x_size, 3);
|
||||
ASSERT_EQ(f_size, 2);
|
||||
ASSERT_EQ(b_size, 1);
|
||||
for (int f = 0; f < f_size; f++)
|
||||
for (int y = 0; y < y_size; ++y) {
|
||||
for (int x = 0; x < x_size; ++x) {
|
||||
ASSERT_NEAR(output_vec[f][y][x], ((float)output_ptr[f * y_size * x_size + y * x_size + x]), 1e-5f) <<
|
||||
" x="<< x << " y=" << y << " f=" << f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(convolution_gpu_onednn, quantized_onednn_convolution_u8s8f32_asymmetric_activations_per_channel) {
|
||||
auto& engine = get_test_engine();
|
||||
if (!engine.get_device_info().supports_immad)
|
||||
return;
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::u8, format::bfyx, { 1, 2, 5, 4 } });
|
||||
auto weights = engine.allocate_memory({ data_types::i8, format::bfyx, { 2, 2, 3, 3 } });
|
||||
auto biases = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 2, 1, 1 } });
|
||||
auto a_zp = engine.allocate_memory({ data_types::u8, format::bfyx, { 1, 2, 1, 1 } });
|
||||
|
||||
set_values<uint8_t>(input, { 1, 2, 3, 4, 5,
|
||||
2, 2, 3, 4, 6,
|
||||
3, 3, 3, 5, 1,
|
||||
1, 1, 1, 1, 1,
|
||||
|
||||
1, 2, 3, 4, 5,
|
||||
2, 2, 3, 4, 6,
|
||||
3, 3, 3, 5, 1,
|
||||
1, 1, 1, 1, 1 });
|
||||
|
||||
set_values<int8_t>(weights, { 1, 2, -1,
|
||||
-2, 1, 2,
|
||||
9, 7, -1,
|
||||
|
||||
9, 0, -4,
|
||||
-1, 3, 2,
|
||||
0, 2, 5,
|
||||
|
||||
1, 2, -1,
|
||||
-2, 1, 2,
|
||||
9, 7, -1,
|
||||
|
||||
9, 0, -4,
|
||||
-1, 3, 2,
|
||||
0, 2, 5 });
|
||||
set_values<uint8_t>(a_zp, { 2, 5 });
|
||||
set_values(biases, { 1.0f, -8.0f });
|
||||
|
||||
VVVF<float> output_vec = {
|
||||
{
|
||||
{ -36.0f, 5.0f, -14.0f },
|
||||
{ -24.0f, -10.0f, -30.0f }
|
||||
},
|
||||
{
|
||||
{ -45.0f, -4.0f, -23.0f },
|
||||
{ -33.0f, -19.0f, -39.0f }
|
||||
} };
|
||||
|
||||
topology topology(
|
||||
input_layout("input", input->get_layout()),
|
||||
data("weights", weights),
|
||||
data("biases", biases),
|
||||
data("a_zp", a_zp),
|
||||
convolution("conv", input_info("input"), { "weights" }, { "biases" }, { }, { "a_zp" }, 1, data_types::f32,
|
||||
{ 2, 2 }, { 0, 0 }, { 1, 1 }, tensor{ 1, 2, 3, 2 }, false),
|
||||
reorder("out", input_info("conv"), format::bfyx, data_types::f32));
|
||||
|
||||
ExecutionConfig config;
|
||||
ov::intel_gpu::ImplementationDesc conv_impl = { format::byxf, "", impl_types::onednn };
|
||||
config.set_property(ov::intel_gpu::force_implementations(ov::intel_gpu::ImplForcingMap{ { "conv", conv_impl }}));
|
||||
config.set_property(ov::intel_gpu::optimize_data(true));
|
||||
config.set_property(ov::intel_gpu::queue_type(QueueTypes::in_order));
|
||||
|
||||
network network(engine, topology, config);
|
||||
network.set_input_data("input", input);
|
||||
|
||||
auto outputs = network.execute();
|
||||
ASSERT_EQ(outputs.begin()->first, "out");
|
||||
|
||||
auto output_memory = outputs.at("out").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output_memory, get_test_stream());
|
||||
|
||||
auto output_layout = output_memory->get_layout();
|
||||
int y_size = output_layout.spatial(1);
|
||||
int x_size = output_layout.spatial(0);
|
||||
int f_size = output_layout.feature();
|
||||
int b_size = output_layout.batch();
|
||||
ASSERT_EQ(output_layout.format, format::bfyx);
|
||||
ASSERT_EQ(y_size, 2);
|
||||
ASSERT_EQ(x_size, 3);
|
||||
ASSERT_EQ(f_size, 2);
|
||||
ASSERT_EQ(b_size, 1);
|
||||
for (int f = 0; f < f_size; f++)
|
||||
for (int y = 0; y < y_size; ++y) {
|
||||
for (int x = 0; x < x_size; ++x) {
|
||||
ASSERT_NEAR(output_vec[f][y][x], ((float)output_ptr[f * y_size * x_size + y * x_size + x]), 1e-5f) <<
|
||||
" x="<< x << " y=" << y << " f=" << f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ENABLE_ONEDNN_FOR_GPU
|
||||
|
||||
template <typename T>
|
||||
|
||||
+1
-1
Submodule src/plugins/intel_gpu/thirdparty/onednn_gpu updated: fbec3e25a5...d3af87710f.
Reference in new issue
Block a user