Snippets: precision propagation (#14996)
This commit is contained in:
1 parent
5fa95ff19d
commit
087b10ff00
48 files changed
+2066
-327
No files matched your search
@@ -117,7 +117,6 @@ xfail_issue_onnx_models_140 = xfail_test(reason="https://github.com/onnx/models/
|
||||
|
||||
xfail_issue_63033 = xfail_test(reason="BatchNormalization: Training mode is not supported")
|
||||
xfail_issue_63036 = xfail_test(reason="Changes in ConvTranspose padding")
|
||||
xfail_issue_63039 = xfail_test(reason="Result mismatches with UINT8 operations")
|
||||
xfail_issue_63043 = xfail_test(reason="Recurrent node expects constants as W, R, B inputs.")
|
||||
|
||||
skip_rng_tests = pytest.mark.skip(reason="Tests use random number generator with no seed.")
|
||||
|
||||
@@ -37,7 +37,6 @@ from tests import (
|
||||
xfail_issue_58033,
|
||||
xfail_issue_63033,
|
||||
xfail_issue_63036,
|
||||
xfail_issue_63039,
|
||||
xfail_issue_63043,
|
||||
xfail_issue_63137,
|
||||
xfail_issue_63138,
|
||||
@@ -278,10 +277,6 @@ tests_expected_to_fail = [
|
||||
"OnnxBackendNodeModelTest.test_batchnorm_example_training_mode_cpu",
|
||||
),
|
||||
(xfail_issue_63036, "OnnxBackendNodeModelTest.test_convtranspose_autopad_same_cpu"),
|
||||
(
|
||||
xfail_issue_63039,
|
||||
"OnnxBackendNodeModelTest.test_div_uint8_cpu",
|
||||
),
|
||||
(
|
||||
xfail_issue_63043,
|
||||
"OnnxBackendNodeModelTest.test_gru_batchwise_cpu",
|
||||
|
||||
@@ -122,7 +122,6 @@ xfail_issue_onnx_models_140 = xfail_test(reason="https://github.com/onnx/models/
|
||||
|
||||
xfail_issue_63033 = xfail_test(reason="BatchNormalization: Training mode is not supported")
|
||||
xfail_issue_63036 = xfail_test(reason="Changes in ConvTranspose padding")
|
||||
xfail_issue_63039 = xfail_test(reason="Result mismatches with UINT8 operations")
|
||||
xfail_issue_63043 = xfail_test(reason="Recurrent node expects constants as W, R, B inputs.")
|
||||
|
||||
skip_rng_tests = pytest.mark.skip(reason="Tests use random number generator with no seed.")
|
||||
|
||||
@@ -37,7 +37,6 @@ from tests_compatibility import (
|
||||
xfail_issue_58033,
|
||||
xfail_issue_63033,
|
||||
xfail_issue_63036,
|
||||
xfail_issue_63039,
|
||||
xfail_issue_63043,
|
||||
xfail_issue_63137,
|
||||
xfail_issue_63138,
|
||||
@@ -282,10 +281,6 @@ tests_expected_to_fail = [
|
||||
"OnnxBackendNodeModelTest.test_batchnorm_example_training_mode_cpu",
|
||||
),
|
||||
(xfail_issue_63036, "OnnxBackendNodeModelTest.test_convtranspose_autopad_same_cpu"),
|
||||
(
|
||||
xfail_issue_63039,
|
||||
"OnnxBackendNodeModelTest.test_div_uint8_cpu",
|
||||
),
|
||||
(
|
||||
xfail_issue_63043,
|
||||
"OnnxBackendNodeModelTest.test_gru_batchwise_cpu",
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace snippets {
|
||||
|
||||
auto getRegisters(std::shared_ptr<ngraph::Node>& n) -> ngraph::snippets::RegInfo;
|
||||
|
||||
typedef std::pair<std::function<std::shared_ptr<Emitter>(const std::shared_ptr<ngraph::Node>&)>,
|
||||
std::function<std::set<std::vector<element::Type>>(const std::shared_ptr<ngraph::Node>&)>> jitters_value;
|
||||
/**
|
||||
* @interface TargetMachine
|
||||
* @brief Base class Target machine representation. Target derives from this class to provide generator information about supported emitters
|
||||
@@ -51,7 +53,16 @@ public:
|
||||
if (jitter == jitters.end()) {
|
||||
throw ngraph_error(std::string("Target code emitter is not available for ") + type.name + " operation.");
|
||||
}
|
||||
return jitter->second;
|
||||
return jitter->second.first;
|
||||
}
|
||||
|
||||
std::function<std::set<std::vector<element::Type>>(const std::shared_ptr<ngraph::Node>&)>
|
||||
get_supported_precisions(const ngraph::DiscreteTypeInfo type) const {
|
||||
auto jitter = jitters.find(type);
|
||||
if (jitter == jitters.end()) {
|
||||
throw ngraph_error(std::string("Target code emitter is not available for ") + type.name + " operation.");
|
||||
}
|
||||
return jitter->second.second;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +75,7 @@ public:
|
||||
virtual ~TargetMachine() = default;
|
||||
|
||||
protected:
|
||||
std::map<const ngraph::DiscreteTypeInfo, std::function<std::shared_ptr<Emitter>(std::shared_ptr<ngraph::Node>)>> jitters;
|
||||
std::map<const ngraph::DiscreteTypeInfo, jitters_value> jitters;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -101,11 +101,17 @@ public:
|
||||
bool is_quantized() const { return config.m_is_quantized; }
|
||||
bool has_type_relaxed_ops() const { return config.m_has_type_relaxed_ops; }
|
||||
bool has_domain_sensitive_ops() const { return config.m_has_domain_sensitive_ops; }
|
||||
|
||||
snippets::Schedule generate(const BlockedShapeVector& output_shapes, const BlockedShapeVector& input_shapes, ngraph::pass::Manager& opt,
|
||||
snippets::Schedule generate(const BlockedShapeVector& output_shapes,
|
||||
const BlockedShapeVector& input_shapes,
|
||||
ngraph::pass::Manager& pre_dialect,
|
||||
ngraph::pass::Manager& post_dialect,
|
||||
ngraph::pass::Manager& post_precision,
|
||||
const void* compile_params = nullptr);
|
||||
snippets::Schedule generate(const BlockedShapeVector& output_shapes, const BlockedShapeVector& input_shapes, const void* compile_params = nullptr);
|
||||
snippets::Schedule generate(ngraph::pass::Manager &opt, const void* compile_params = nullptr);
|
||||
snippets::Schedule generate(ngraph::pass::Manager& pre_dialect,
|
||||
ngraph::pass::Manager& post_dialect,
|
||||
ngraph::pass::Manager& post_precision,
|
||||
const void* compile_params = nullptr);
|
||||
snippets::Schedule generate(const void* compile_params = nullptr);
|
||||
ov::PartialShape canonicalize(const BlockedShapeVector& output_shapes, const BlockedShapeVector& input_shapes);
|
||||
std::vector<PartialShape> reshape_body(const std::vector<PartialShape>& input_shapes);
|
||||
@@ -132,6 +138,8 @@ public:
|
||||
// This check returns True if Constant op which is input of this op should be inside Subgraph body
|
||||
static auto constant_input_should_be_inside_body(const std::shared_ptr<ov::Node>& node) -> bool;
|
||||
|
||||
static bool check_broadcast(const std::shared_ptr<const ov::Node>& node) noexcept;
|
||||
|
||||
private:
|
||||
void align_element_types(const BlockedShapeVector& outputShapes, const BlockedShapeVector& inputShapes);
|
||||
void convert_to_snippet_dialect();
|
||||
@@ -164,8 +172,6 @@ private:
|
||||
public:
|
||||
// True if Subgraph contains FakeQuantize -> FQ decomposition should be called
|
||||
bool m_is_quantized = false;
|
||||
// True if we should align element types indise body
|
||||
bool m_is_needed_to_align_precision = false;
|
||||
// True if Subgraph contains TypeRelaxed nodes -> for several streams in tp mode we should copy body using mutexes
|
||||
// because TypeRelaxed::copy_with_new_inputs() isn't save-thread method
|
||||
bool m_has_type_relaxed_ops = false;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ngraph/pass/graph_rewrite.hpp>
|
||||
#include <ngraph/pattern/matcher.hpp>
|
||||
|
||||
namespace ngraph {
|
||||
namespace snippets {
|
||||
namespace pass {
|
||||
|
||||
/**
|
||||
* @interface AlignElementType
|
||||
* @brief Wrap sequence of operations which doesn't support execution on original element type by ConvertSaturation
|
||||
* and reset element type for type relaxed nodes inside body to align element type between nodes.
|
||||
* Example 1:
|
||||
* - After FQ decomposition there may be Convert[U8/I8]. If after the Convert there are other operations
|
||||
* that don't support U8/I8, new ConvertSaturation[exec_type] will be inserted after the FQ decomposition
|
||||
* to execute these operations on supported element type
|
||||
* Example 2:
|
||||
* - Input[I8] -> Unsupported I8 op -> Movement op -> Output[I8]. There will be inserted two ConvertSaturation:
|
||||
* * ConvertSatiration[exec_type] before op which is unsupported I8
|
||||
* * ConvertSaturation[I8] before Movement op to return original low precision.
|
||||
* Note: We cannot just remove original Convert[I8/U8] in Example 1 because we should cover two things:
|
||||
* * allow execution of operations on supported element type for them
|
||||
* * keep computations mathematically equivalent to the original function
|
||||
* Thus, for these cases we should have the following pipeline: FP32 -> Convert[I8/U8] -> Convert[FP32] -> FP32
|
||||
* Note: We shouldn't call validate_and_infer_type() after Convert insertions to avoid element type conflicts on inputs of ops
|
||||
* @ingroup snippets
|
||||
*/
|
||||
class AlignElementType: public ngraph::pass::FunctionPass {
|
||||
public:
|
||||
OPENVINO_RTTI("AlignElementType", "0");
|
||||
AlignElementType(const ov::element::Type exec_type = ov::element::f32);
|
||||
bool run_on_model(const std::shared_ptr<ngraph::Function>& m) override;
|
||||
|
||||
static bool opNeedsAlignElementType(const std::shared_ptr<ov::Node>& n, const ov::element::Type exec_type = ov::element::f32);
|
||||
private:
|
||||
ov::element::Type exec_type;
|
||||
};
|
||||
|
||||
} // namespace pass
|
||||
} // namespace snippets
|
||||
} // namespace ngraph
|
||||
@@ -29,7 +29,7 @@ namespace pass {
|
||||
*
|
||||
* Expand brackets:
|
||||
* round(x * (levels-1) / (ih - il) - il * (levels-1) / (ih - il)) * (oh - ol) / (levels-1) + ol
|
||||
*
|
||||
*
|
||||
* Marking:
|
||||
* - isc := (levels-1) / (ih - il)
|
||||
* - ish := -il * isc
|
||||
@@ -37,7 +37,7 @@ namespace pass {
|
||||
* - osh := ol
|
||||
* Final expression:
|
||||
* round(x * isc + ish) * osc + osh
|
||||
*
|
||||
*
|
||||
* Some optimizations (example for scalars):
|
||||
* 1. If output element type of FQ is U8 and il = 0, ish = 0, osc = 1, osh = 0, there is enough expression: x * isc
|
||||
* 2. If output element type of FQ is I8 and ish ~= 128, osc = 1, osh ~= -128, il * isc ~= -128, ih * isc ~= 127 there is enough expression: x * isc
|
||||
@@ -54,7 +54,6 @@ class FakeQuantizeDecomposition : public ngraph::pass::MatcherPass {
|
||||
public:
|
||||
FakeQuantizeDecomposition();
|
||||
|
||||
static bool isAllScalarConstant(const std::shared_ptr<const ngraph::Node>& node);
|
||||
static bool getScalesAndShifts(const std::shared_ptr<const ngraph::op::v0::FakeQuantize>& fq_node,
|
||||
std::vector<float>& cl,
|
||||
std::vector<float>& ch,
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <ngraph/pass/pass.hpp>
|
||||
#include "snippets/generator.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace snippets {
|
||||
namespace pass {
|
||||
|
||||
/**
|
||||
* @class PropagatePrecision
|
||||
* @ingroup snippets
|
||||
* @brief PropagatePrecision transformation propagate precision from parameters to results.
|
||||
*/
|
||||
class PropagatePrecision: public ngraph::pass::FunctionPass {
|
||||
public:
|
||||
OPENVINO_RTTI("PropagatePrecision", "0");
|
||||
PropagatePrecision(const std::shared_ptr<const TargetMachine>& target_machine);
|
||||
bool run_on_model(const std::shared_ptr<ov::Model>& m) override;
|
||||
|
||||
static std::vector<element::Type> get_precisions(
|
||||
const std::vector<element::Type>& input_precisions,
|
||||
const std::set<std::vector<element::Type>>& supported_precisions) noexcept;
|
||||
|
||||
// if can_be_removed returns true then actual convertion (actual_before => actual_after)
|
||||
// can be replaced to required (actual_before => required_after)
|
||||
static bool can_be_removed(
|
||||
const element::Type& actual_before,
|
||||
const element::Type& actual_after,
|
||||
const element::Type& required_after) noexcept;
|
||||
|
||||
// if can_be_fused returns true then actual convertion can be replaced to required
|
||||
static bool can_be_fused(
|
||||
const element::Type& actual,
|
||||
const element::Type& required) noexcept;
|
||||
|
||||
private:
|
||||
const std::shared_ptr<const TargetMachine> target_machine;
|
||||
};
|
||||
|
||||
} // namespace pass
|
||||
} // namespace snippets
|
||||
} // namespace ngraph
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "snippets/pass/insert_movebroadcast.hpp"
|
||||
#include "snippets/pass/broadcast_to_movebroadcast.hpp"
|
||||
#include "snippets/pass/load_movebroadcast_to_broadcastload.hpp"
|
||||
#include "snippets/pass/propagate_precision.hpp"
|
||||
#include "snippets/pass/assign_registers.hpp"
|
||||
#include "snippets/pass/convert_constants.hpp"
|
||||
#include "snippets/pass/convert_power_to_powerstatic.hpp"
|
||||
@@ -18,7 +19,6 @@
|
||||
#include "snippets/pass/insert_loops.hpp"
|
||||
#include "snippets/pass/transpose_decomposition.hpp"
|
||||
#include "snippets/pass/transform_convert.hpp"
|
||||
#include "snippets/pass/align_element_type.hpp"
|
||||
#include "snippets/pass/matmul_to_brgemm.hpp"
|
||||
#include "snippets/pass/fuse_transpose_brgemm.hpp"
|
||||
#include "snippets/pass/softmax_decomposition.hpp"
|
||||
@@ -62,10 +62,6 @@ void snippets::op::Subgraph::init_config() {
|
||||
ov::is_type<ov::op::v0::FakeQuantize>(op);
|
||||
config.m_has_type_relaxed_ops = config.m_has_type_relaxed_ops ||
|
||||
std::dynamic_pointer_cast<ov::op::TypeRelaxedBase>(op);
|
||||
config.m_is_needed_to_align_precision = config.m_is_needed_to_align_precision ||
|
||||
is_quantized() ||
|
||||
has_type_relaxed_ops() ||
|
||||
snippets::pass::AlignElementType::opNeedsAlignElementType(op, execution_element_type);
|
||||
config.m_has_domain_sensitive_ops = config.m_has_domain_sensitive_ops ||
|
||||
ov::is_type<ov::op::v1::Transpose>(op) ||
|
||||
ov::is_type<ov::op::v1::Softmax>(op) ||
|
||||
@@ -359,6 +355,14 @@ ov::PartialShape snippets::op::Subgraph::canonicalize(const BlockedShapeVector&
|
||||
return master_shape;
|
||||
}
|
||||
|
||||
bool snippets::op::Subgraph::check_broadcast(const std::shared_ptr<const ov::Node>& node) noexcept {
|
||||
const auto elementwise = std::dynamic_pointer_cast<const ov::op::util::BinaryElementwiseArithmetic>(node);
|
||||
return
|
||||
(elementwise == nullptr) ||
|
||||
(elementwise->get_input_partial_shape(0).size() == elementwise->get_input_partial_shape(1).size()) ||
|
||||
(elementwise->get_autob().m_type != ov::op::AutoBroadcastType::PDPD);
|
||||
}
|
||||
|
||||
void snippets::op::Subgraph::align_element_types(const BlockedShapeVector& outputShapes,
|
||||
const BlockedShapeVector& inputShapes) {
|
||||
// We should insert Convert before Results to set original output element type if needed
|
||||
@@ -369,35 +373,34 @@ void snippets::op::Subgraph::align_element_types(const BlockedShapeVector& outpu
|
||||
const auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
body_results[i]->get_input_node_shared_ptr(0), needed_out_type);
|
||||
body_results[i]->set_argument(0, convert);
|
||||
body_results[i]->validate_and_infer_types();
|
||||
}
|
||||
}
|
||||
|
||||
// We should change existing element type to original for Parameters if needed
|
||||
const auto& body_parameters = body_ptr()->get_parameters();
|
||||
const auto& parameters = body_ptr()->get_parameters();
|
||||
for (size_t i = 0; i < inputShapes.size(); ++i) {
|
||||
const auto needed_in_type = std::get<2>(inputShapes[i]);
|
||||
if (body_parameters[i]->get_element_type() != needed_in_type) {
|
||||
body_parameters[i]->set_element_type(needed_in_type);
|
||||
config.m_is_needed_to_align_precision = true;
|
||||
const auto& parameter = parameters[i];
|
||||
if (parameter->get_element_type() != needed_in_type) {
|
||||
const auto parameter_output = parameter->output(0);
|
||||
const auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
parameter_output,
|
||||
parameter_output.get_element_type());
|
||||
ngraph::copy_runtime_info(parameter, convert);
|
||||
|
||||
for (const auto input : parameter_output.get_target_inputs()) {
|
||||
const auto& input_node = input.get_node();
|
||||
if (input_node == convert.get()) {
|
||||
continue;
|
||||
}
|
||||
input_node->set_argument(input.get_index(), convert->output(0));
|
||||
}
|
||||
|
||||
parameter->set_element_type(needed_in_type);
|
||||
parameter->validate_and_infer_types();
|
||||
}
|
||||
}
|
||||
|
||||
// We should align element type inside body using the corresponding pass:
|
||||
// - Insert Convert before operations that doesn't support original element type for execution
|
||||
// - Insert reverse Convert before operations that support original element type
|
||||
// but have inputs that doesn't support it (because before them will be inserted Convert with exec_type - first point)
|
||||
// - Then we should use ConstantFolding pass to convert element type of Scalars before inference.
|
||||
// - Eliminate redundant Converts which can be inserted in AlignElementType() pass
|
||||
ngraph::pass::Manager manager;
|
||||
if (config.m_is_needed_to_align_precision) {
|
||||
manager.register_pass<snippets::pass::AlignElementType>(execution_element_type);
|
||||
manager.register_pass<ov::pass::ConstantFolding>();
|
||||
// TODO [100041] : In some cases AlignElementType pass can insert extra Convert because
|
||||
// the pass doesn't know real precisions in real time.
|
||||
// We call EliminateConverts pass to remove them
|
||||
manager.register_pass<ov::pass::EliminateConvert>();
|
||||
}
|
||||
manager.run_passes(body_ptr());
|
||||
}
|
||||
|
||||
void snippets::op::Subgraph::initialize_buffer_scratchpad_size() {
|
||||
@@ -602,24 +605,39 @@ snippets::Schedule snippets::op::Subgraph::generate(const BlockedShapeVector& ou
|
||||
|
||||
snippets::Schedule snippets::op::Subgraph::generate(const BlockedShapeVector& output_shapes,
|
||||
const BlockedShapeVector& input_shapes,
|
||||
ngraph::pass::Manager& opt,
|
||||
ngraph::pass::Manager& pre_dialect,
|
||||
ngraph::pass::Manager& post_dialect,
|
||||
ngraph::pass::Manager& post_precision,
|
||||
const void* compile_params) {
|
||||
canonicalize(output_shapes, input_shapes);
|
||||
return generate(opt, compile_params);
|
||||
return generate(pre_dialect, post_dialect, post_precision, compile_params);
|
||||
}
|
||||
|
||||
snippets::Schedule snippets::op::Subgraph::generate(const void* compile_params) {
|
||||
auto mngr = ngraph::pass::Manager();
|
||||
return generate(mngr, compile_params);
|
||||
return generate(mngr, mngr, mngr, compile_params);
|
||||
}
|
||||
|
||||
snippets::Schedule snippets::op::Subgraph::generate(ngraph::pass::Manager& opt, const void* compile_params) {
|
||||
snippets::Schedule snippets::op::Subgraph::generate(
|
||||
ngraph::pass::Manager& pre_dialect,
|
||||
ngraph::pass::Manager& post_dialect,
|
||||
ngraph::pass::Manager& post_precision,
|
||||
const void* compile_params) {
|
||||
INTERNAL_OP_SCOPE(Subgraph);
|
||||
OV_ITT_SCOPED_TASK(ngraph::pass::itt::domains::SnippetsTransform, "Snippets::op::generate")
|
||||
NGRAPH_CHECK(m_generator != nullptr, "generate is called while generator is not set");
|
||||
|
||||
pre_dialect.run_passes(body_ptr());
|
||||
convert_to_snippet_dialect();
|
||||
opt.run_passes(body_ptr());
|
||||
post_dialect.run_passes(body_ptr());
|
||||
|
||||
ngraph::pass::Manager precision_manager;
|
||||
precision_manager.register_pass<snippets::pass::PropagatePrecision>(m_generator->get_target_machine());
|
||||
precision_manager.register_pass<ngraph::pass::ConstantFolding>();
|
||||
precision_manager.register_pass<snippets::pass::ConvertConstantsToScalars>();
|
||||
precision_manager.run_passes(body_ptr());
|
||||
|
||||
post_precision.run_passes(body_ptr());
|
||||
|
||||
// After all passes, when all optimizations are completed and all MemoryAccess ops are inserted,
|
||||
// we can calculate common buffer scratchpad size and propagate offset from Buffer to the corresponding MemoryAccess ops
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <snippets/itt.hpp>
|
||||
|
||||
#include "snippets/snippets_isa.hpp"
|
||||
#include "snippets/op/convert_saturation.hpp"
|
||||
#include "snippets/pass/align_element_type.hpp"
|
||||
#include "snippets/utils.hpp"
|
||||
#include "ov_ops/type_relaxed.hpp"
|
||||
#include "ngraph/op/util/op_types.hpp"
|
||||
|
||||
#include <ngraph/rt_info.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
inline auto is_in_op(const std::shared_ptr<ov::Node>& n) -> bool {
|
||||
return ov::is_type<ov::op::v0::Parameter>(n)
|
||||
|| ov::is_type<ov::op::v0::Constant>(n);
|
||||
}
|
||||
|
||||
// At the moment Subgraph supports only Eltwise, Select, Convert, Broadcast and FQ (which is decomposed into Eltwises and Convert) with
|
||||
// Softmax (which is decomposed into Eltwises as well)
|
||||
// And only Eltwise and Select ops supports execution only in "exec_type". So we can check op type from the opposite
|
||||
// NOTE: This check is only for executable which isn't Parameter/Constant/Result
|
||||
inline auto op_supports_only_exec_type(const std::shared_ptr<ov::Node>& n) -> bool {
|
||||
return !is_in_op(n) &&
|
||||
!ov::is_type<ov::op::v0::Result>(n) &&
|
||||
!ov::is_type<ov::op::v1::Transpose>(n) &&
|
||||
!ov::is_type<ov::op::v0::Convert>(n) &&
|
||||
!ov::is_type<ov::op::v1::Broadcast>(n) &&
|
||||
!ov::is_type<ov::op::v3::Broadcast>(n);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ngraph::snippets::pass::AlignElementType::AlignElementType(const ov::element::Type exec_type) : exec_type(exec_type) { }
|
||||
|
||||
bool ngraph::snippets::pass::AlignElementType::run_on_model(const std::shared_ptr<ov::Model> &m) {
|
||||
RUN_ON_FUNCTION_SCOPE(AlignElementType);
|
||||
|
||||
auto insertConvert = [](const std::shared_ptr<ov::Node>& op, const size_t idx, const ov::element::Type& element_type) -> void {
|
||||
auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(op->input(idx).get_source_output(), element_type);
|
||||
ngraph::copy_runtime_info(op->get_input_node_shared_ptr(idx), convert);
|
||||
op->set_argument(idx, convert);
|
||||
};
|
||||
|
||||
// NOTE: We don't call validate_and_infer_types() to avoid precision conflicts on inputs
|
||||
bool rewritten = false;
|
||||
auto ops = m->get_ordered_ops();
|
||||
for (auto& op : ops) {
|
||||
if (is_in_op(op)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op_supports_only_exec_type(op)) {
|
||||
for (size_t i = 0; i < op->inputs().size(); i++) {
|
||||
auto shared_input = op->get_input_node_shared_ptr(i);
|
||||
auto existing_convert = ov::as_type_ptr<ov::op::v0::Convert>(shared_input);
|
||||
// We should insert Convert before Ops, which supports only exec element type, only when:
|
||||
// - Input is Convert with unsupported destination type
|
||||
// - Input is Op which support any element type
|
||||
// We couldn't unite these conditions and just check that element type isn't supported exec type
|
||||
// because we don't call validate_and_infer_types() so we don't know new precisions after setting of original
|
||||
// input and output element types
|
||||
if ((existing_convert && existing_convert->get_destination_type() != exec_type) ||
|
||||
(!op_supports_only_exec_type(shared_input))) {
|
||||
insertConvert(op, i, exec_type);
|
||||
rewritten |= true;
|
||||
}
|
||||
}
|
||||
if (auto tr_node = std::dynamic_pointer_cast<ov::op::TypeRelaxedBase>(op)) {
|
||||
tr_node->set_overridden_output_type(exec_type, 0);
|
||||
rewritten |= true;
|
||||
}
|
||||
} else { // branch for Movement ops, MatMul ops in the future and for the Convert, Result
|
||||
for (size_t i = 0; i < op->inputs().size(); i++) {
|
||||
auto shared_input = op->get_input_node_shared_ptr(i);
|
||||
// it's original element type because we don't use validate_and_infer_type() anywhere
|
||||
const auto original_eltype = op->input(i).get_element_type();
|
||||
// If before op there is another op that doesn't support execution on original element type, we know that
|
||||
// before this op will be inserted reverse Convert to support execution on supported element type (first branch of condition).
|
||||
// So we should return original element type for operations that can support low precision
|
||||
if (op_supports_only_exec_type(shared_input) && original_eltype != exec_type) {
|
||||
insertConvert(op, i, original_eltype);
|
||||
rewritten |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rewritten;
|
||||
}
|
||||
|
||||
bool ngraph::snippets::pass::AlignElementType::opNeedsAlignElementType(const std::shared_ptr<ov::Node>& op, const ov::element::Type exec_type) {
|
||||
// At the moment Snippets support only Eltwise/Convert/FQ/Select/Softmax/Broadcast which one output so we can just call get_element_type()
|
||||
return op_supports_only_exec_type(op) && op->get_element_type() != exec_type;
|
||||
}
|
||||
@@ -212,7 +212,11 @@ const std::set<ngraph::element::Type> ngraph::snippets::pass::TokenizeSnippets::
|
||||
{ ngraph::element::f32, ngraph::element::bf16, ngraph::element::i8, ngraph::element::u8 };
|
||||
|
||||
bool TokenizeSnippets::AppropriateForSubgraph(const std::shared_ptr<const Node> &node) {
|
||||
return is_supported_op(node) && has_supported_in_out(node) && node->get_control_dependencies().empty();
|
||||
return
|
||||
is_supported_op(node) &&
|
||||
has_supported_in_out(node) &&
|
||||
node->get_control_dependencies().empty() &&
|
||||
snippets::op::Subgraph::check_broadcast(node);
|
||||
}
|
||||
|
||||
TokenizeSnippets::TokenizeSnippets() {
|
||||
|
||||
@@ -36,11 +36,6 @@ bool isValidRangesInputs(const std::shared_ptr<ngraph::opset1::FakeQuantize>& fq
|
||||
});
|
||||
}
|
||||
|
||||
bool is_scalar_constant(const std::shared_ptr<ngraph::Node>& source_output_node) {
|
||||
return ngraph::is_type<ngraph::opset1::Constant>(source_output_node) &&
|
||||
ngraph::shape_size(source_output_node->get_shape()) == 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ngraph::snippets::pass::FakeQuantizeDecomposition::FakeQuantizeDecomposition() {
|
||||
@@ -182,13 +177,6 @@ ngraph::snippets::pass::FakeQuantizeDecomposition::FakeQuantizeDecomposition() {
|
||||
register_matcher(m, callback);
|
||||
}
|
||||
|
||||
bool ngraph::snippets::pass::FakeQuantizeDecomposition::isAllScalarConstant(const std::shared_ptr<const ngraph::Node>& node) {
|
||||
return is_scalar_constant(node->get_input_node_shared_ptr(1)) &&
|
||||
is_scalar_constant(node->get_input_node_shared_ptr(2)) &&
|
||||
is_scalar_constant(node->get_input_node_shared_ptr(3)) &&
|
||||
is_scalar_constant(node->get_input_node_shared_ptr(4));
|
||||
}
|
||||
|
||||
bool ngraph::snippets::pass::FakeQuantizeDecomposition::getScalesAndShifts(
|
||||
const std::shared_ptr<const ngraph::opset1::FakeQuantize>& fq_node,
|
||||
std::vector<float>& cl,
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "snippets/pass/propagate_precision.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <memory>
|
||||
#include "ov_ops/type_relaxed.hpp"
|
||||
#include "snippets/itt.hpp"
|
||||
#include "ngraph/rt_info.hpp"
|
||||
|
||||
using namespace ngraph;
|
||||
|
||||
ngraph::snippets::pass::PropagatePrecision::PropagatePrecision(
|
||||
const std::shared_ptr<const TargetMachine>& target_machine) : target_machine(target_machine) {
|
||||
}
|
||||
|
||||
bool ngraph::snippets::pass::PropagatePrecision::run_on_model(const std::shared_ptr<ov::Model>& f) {
|
||||
RUN_ON_MODEL_SCOPE(PropagatePrecision);
|
||||
OV_ITT_SCOPED_TASK(ngraph::pass::itt::domains::SnippetsTransform, "Snippets::op::PropagatePrecision")
|
||||
|
||||
std::unordered_map<std::shared_ptr<ngraph::opset1::Result>, element::Type> result_types;
|
||||
auto results = f->get_results();
|
||||
for (auto& result : results) {
|
||||
result_types.emplace(result, result->get_input_element_type(0));
|
||||
}
|
||||
|
||||
bool was_updated = true;
|
||||
for (const auto& op : f->get_ordered_ops()) {
|
||||
auto type_info = op->get_type_info();
|
||||
OPENVINO_ASSERT(
|
||||
target_machine->has(type_info),
|
||||
"operation '" + std::string(type_info.version_id) + "::" + std::string(type_info.name) + "' was not found in target machine");
|
||||
|
||||
auto exec = target_machine->get_supported_precisions(type_info);
|
||||
const auto supported_precisions = exec(op);
|
||||
if (supported_precisions.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// There are two operation types which break precision propagation:
|
||||
// 1) Existing convertion operations. Solution: remove convertion
|
||||
// operation before general algo
|
||||
// 2) Type relaxed based operations. Will be resolved by snippet opset.
|
||||
|
||||
auto input_precisions_were_changed = false;
|
||||
|
||||
for (const auto& input : op->inputs()) {
|
||||
const auto convert = ngraph::as_type<snippets::op::ConvertSaturation>(input.get_source_output().get_node());
|
||||
if (convert == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto precision_before = convert->get_input_element_type(0);
|
||||
const auto precision_after = convert->get_output_element_type(0);
|
||||
if (can_be_removed(precision_before, precision_after, precision_before)) {
|
||||
op->set_argument(input.get_index(), convert->input(0).get_source_output());
|
||||
input_precisions_were_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<element::Type> input_precisions;
|
||||
for (const auto& input : op->inputs()) {
|
||||
const auto input_precision = input.get_source_output().get_element_type();
|
||||
input_precisions.push_back(input_precision);
|
||||
}
|
||||
|
||||
assert(std::all_of(
|
||||
supported_precisions.begin(),
|
||||
supported_precisions.end(),
|
||||
[&input_precisions](const std::vector<element::Type>& precisions) {
|
||||
return precisions.size() == input_precisions.size();
|
||||
}) && "input precisions count is not equal for supported precisions");
|
||||
|
||||
// update input precisions
|
||||
// if possible then convert precisions to supported
|
||||
if (!supported_precisions.empty() &&
|
||||
std::all_of(
|
||||
supported_precisions.begin(),
|
||||
supported_precisions.end(),
|
||||
[&input_precisions](const std::vector<element::Type>& precisions) {
|
||||
return precisions != input_precisions;
|
||||
})) {
|
||||
auto precisions = get_precisions(input_precisions,
|
||||
supported_precisions);
|
||||
OPENVINO_ASSERT(
|
||||
!precisions.empty(),
|
||||
"there are no supported precisions for operation '" + std::string(type_info.version_id) + "::" + std::string(type_info.name) + "'");
|
||||
|
||||
auto find_convert = [](
|
||||
const ngraph::Output<ngraph::Node> parent_output,
|
||||
const ngraph::element::Type convert_type) -> snippets::op::ConvertSaturation* {
|
||||
for (const auto& input : parent_output.get_target_inputs()) {
|
||||
const auto child = ngraph::as_type<snippets::op::ConvertSaturation>(input.get_node());
|
||||
if ((child != nullptr) && (child->get_output_element_type(0) == convert_type)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < op->get_input_size(); ++i) {
|
||||
const auto& op_input = op->input(i);
|
||||
const auto& required_after = precisions[i];
|
||||
auto parent_output = op_input.get_source_output();
|
||||
const auto actual_before = parent_output.get_element_type();
|
||||
if (actual_before != required_after) {
|
||||
was_updated = true;
|
||||
input_precisions_were_changed = true;
|
||||
auto existing_convert = ngraph::as_type<ngraph::snippets::op::ConvertSaturation>(
|
||||
parent_output.get_node());
|
||||
|
||||
if (existing_convert == nullptr) {
|
||||
existing_convert = find_convert(parent_output, required_after);
|
||||
if (existing_convert != nullptr) {
|
||||
// reuse existing convert
|
||||
op->set_argument(op_input.get_index(), existing_convert->shared_from_this());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing_convert == nullptr) {
|
||||
// create new Convert
|
||||
auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
parent_output,
|
||||
required_after);
|
||||
ngraph::copy_runtime_info(parent_output.get_node_shared_ptr(), convert);
|
||||
op->set_argument(op_input.get_index(), convert);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto actual_before = existing_convert->get_input_element_type(0);
|
||||
const auto actual_after = existing_convert->get_output_element_type(0);
|
||||
|
||||
if (can_be_removed(actual_before, actual_after, required_after)) {
|
||||
// remove existing convert
|
||||
existing_convert->output(0).replace(parent_output);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (can_be_fused(actual_after, required_after)) {
|
||||
// fuse existing convert
|
||||
auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
existing_convert->get_input_node_shared_ptr(0),
|
||||
required_after);
|
||||
ngraph::copy_runtime_info(parent_output.get_node_shared_ptr(), convert);
|
||||
op->set_argument(op_input.get_index(), convert);
|
||||
continue;
|
||||
}
|
||||
|
||||
// create new convert
|
||||
auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
existing_convert->output(0),
|
||||
required_after);
|
||||
ngraph::copy_runtime_info(existing_convert->output(0).get_node()->shared_from_this(), convert);
|
||||
op->set_argument(op_input.get_index(), convert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto type_relaxed_node = std::dynamic_pointer_cast<ov::op::TypeRelaxedBase>(op);
|
||||
if (input_precisions_were_changed || (type_relaxed_node != nullptr)) {
|
||||
// update output precision
|
||||
std::vector<element::Type> op_output_types;
|
||||
for (auto& output : op->outputs()) {
|
||||
op_output_types.push_back(output.get_element_type());
|
||||
}
|
||||
|
||||
if (type_relaxed_node != nullptr) {
|
||||
// TODO: user story 104284
|
||||
// to keep previous functionality
|
||||
// unary and binary element-wise operations are supported
|
||||
// will be replaced to snippets opset later
|
||||
const auto op_element_type = op->get_input_element_type(0);
|
||||
if (type_relaxed_node->get_overridden_output_type(0) != op_element_type) {
|
||||
was_updated = true;
|
||||
OPENVINO_ASSERT(op->get_output_size() == 1ull, "operation with several output is not supported");
|
||||
|
||||
type_relaxed_node->set_overridden_output_type(op_element_type, 0);
|
||||
op->validate_and_infer_types();
|
||||
}
|
||||
} else {
|
||||
op->validate_and_infer_types();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < op->get_output_size(); ++i) {
|
||||
auto output = op->output(i);
|
||||
|
||||
if (output.get_element_type() != op_output_types[i]) {
|
||||
was_updated = true;
|
||||
auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
output,
|
||||
op_output_types[i]);
|
||||
ngraph::copy_runtime_info(output.get_node_shared_ptr(), convert);
|
||||
|
||||
for (auto& input : output.get_target_inputs()) {
|
||||
auto child = input.get_node();
|
||||
if (child == convert.get()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
input.replace_source_output(convert->output(0));
|
||||
|
||||
|
||||
if (ngraph::is_type<ngraph::op::Result>(input.get_node())) {
|
||||
input.get_tensor_ptr()->add_names(output.get_tensor_ptr()->get_names());
|
||||
|
||||
const std::string original_name = op->get_friendly_name();
|
||||
op->set_friendly_name(original_name + "_original");
|
||||
convert->set_friendly_name(original_name);
|
||||
}
|
||||
}
|
||||
output.get_tensor_ptr()->set_names({});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = result_types.begin(); it != result_types.end(); ++it) {
|
||||
const auto result = it->first;
|
||||
const auto actual_type = result->get_input_element_type(0);
|
||||
const auto expected_type = it->second;
|
||||
if (actual_type != it->second) {
|
||||
was_updated = true;
|
||||
auto convert = std::make_shared<ngraph::snippets::op::ConvertSaturation>(
|
||||
result->get_input_node_shared_ptr(0),
|
||||
expected_type);
|
||||
ngraph::copy_runtime_info(result->get_input_node_shared_ptr(0), convert);
|
||||
result->set_argument(0, convert);
|
||||
}
|
||||
}
|
||||
|
||||
return was_updated;
|
||||
}
|
||||
|
||||
bool ngraph::snippets::pass::PropagatePrecision::can_be_removed(
|
||||
const element::Type& actual_before,
|
||||
const element::Type& actual_after,
|
||||
const element::Type& required_after) noexcept {
|
||||
if (actual_before != required_after) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return can_be_fused(actual_after, actual_before);
|
||||
}
|
||||
|
||||
bool ngraph::snippets::pass::PropagatePrecision::can_be_fused(
|
||||
const element::Type& actual,
|
||||
const element::Type& required) noexcept {
|
||||
// custom conditions: between int & float precisions
|
||||
if (((actual == element::bf16) || (actual == element::f16) || (actual == element::f32)) &&
|
||||
((required == element::u8) || (required == element::i8))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((actual == element::f32) && ((required == element::u16) || (required == element::i16))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// general conditions: any new added precision will support
|
||||
return
|
||||
(actual.is_real() == required.is_real()) &&
|
||||
(actual.bitwidth() >= required.bitwidth());
|
||||
}
|
||||
|
||||
std::vector<element::Type> ngraph::snippets::pass::PropagatePrecision::get_precisions(
|
||||
const std::vector<element::Type>& input_precisions,
|
||||
const std::set<std::vector<element::Type>>& supported_precisions_pack) noexcept {
|
||||
bool was_found = false;
|
||||
for (const auto& supported_precisions : supported_precisions_pack) {
|
||||
for (size_t i = 0; i < supported_precisions.size(); ++i) {
|
||||
const auto& supported_precision = supported_precisions[i];
|
||||
const auto& input_precision = input_precisions[i];
|
||||
if ((supported_precision.is_real() != input_precision.is_real()) ||
|
||||
(input_precision.bitwidth() > supported_precision.bitwidth())) {
|
||||
was_found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
was_found = true;
|
||||
}
|
||||
if (was_found) {
|
||||
return supported_precisions;
|
||||
}
|
||||
}
|
||||
|
||||
if (!supported_precisions_pack.empty()) {
|
||||
return *supported_precisions_pack.begin();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -16,7 +16,7 @@ using BlockedShapeVector = ngraph::snippets::op::Subgraph::BlockedShapeVector;
|
||||
class DummyEmitter : public ngraph::snippets::Emitter {
|
||||
public:
|
||||
// Here I pass Add to Emitter, but could be any other op, since it's ignored anyway.
|
||||
DummyEmitter() : ngraph::snippets::Emitter(std::make_shared<ov::op::v1::Add>()) {}
|
||||
DummyEmitter(const std::vector<ov::Node::type_info_t>& custom_opset = {}) : ngraph::snippets::Emitter(std::make_shared<ov::op::v1::Add>()) {}
|
||||
void emit_code(const std::vector<size_t>&,
|
||||
const std::vector<size_t>&,
|
||||
const std::vector<size_t>&,
|
||||
@@ -49,7 +49,9 @@ protected:
|
||||
static std::shared_ptr<ngraph::snippets::op::Subgraph> getSubgraph(const std::shared_ptr<Model>& f);
|
||||
static std::shared_ptr<ngraph::snippets::op::Subgraph> getLoweredSubgraph(const std::shared_ptr<Model>& f,
|
||||
const ov::PartialShape& master_shape,
|
||||
ov::pass::Manager target_optimizations = {},
|
||||
ov::pass::Manager pre_dialect = {},
|
||||
ov::pass::Manager post_dialect = {},
|
||||
ov::pass::Manager post_precision = {},
|
||||
const std::shared_ptr<ngraph::snippets::Generator> generator = nullptr);
|
||||
static std::shared_ptr<ngraph::snippets::op::Subgraph> getTokenizedSubgraph(const std::shared_ptr<Model>& f);
|
||||
ov::PartialShape master_shape{};
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lowering_utils.hpp"
|
||||
#include "snippets_helpers.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
class PrecisionPropagationParamsValues {
|
||||
public:
|
||||
class Actual {
|
||||
public:
|
||||
std::pair<element::Type, element::Type> convertion_before_op1;
|
||||
element::Type convertion_before_op2_1;
|
||||
std::pair<element::Type, element::Type> convertion_before_op2_2;
|
||||
std::set<std::vector<element::Type>> op1_supported_precisions;
|
||||
std::set<std::vector<element::Type>> op2_supported_precisions;
|
||||
};
|
||||
|
||||
class Expected {
|
||||
public:
|
||||
std::pair<element::Type, element::Type> convertion_before_op1;
|
||||
element::Type convertion_before_op2_1;
|
||||
std::pair<element::Type, element::Type> convertion_before_op2_2;
|
||||
element::Type convertion_after_op2;
|
||||
};
|
||||
|
||||
std::vector<element::Type> input_types;
|
||||
Actual actual;
|
||||
Expected expected;
|
||||
};
|
||||
|
||||
typedef std::tuple<
|
||||
std::pair<PartialShape, PartialShape>, // input shapes
|
||||
PrecisionPropagationParamsValues
|
||||
> PrecisionPropagationParams;
|
||||
|
||||
class PrecisionPropagationTest : public TransformationTestsF,
|
||||
public testing::WithParamInterface<PrecisionPropagationParams> {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<PrecisionPropagationParams> obj);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<SnippetsFunctionBase> snippets_function;
|
||||
};
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -11,10 +11,12 @@ namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
DummyTargetMachine::DummyTargetMachine(const std::vector<ov::Node::type_info_t>& custom_opset) {
|
||||
auto dummy_functor = [](const std::shared_ptr<ngraph::Node>& n) {
|
||||
return std::make_shared<DummyEmitter>();
|
||||
DummyTargetMachine::DummyTargetMachine(const std::vector<ov::Node::type_info_t>&custom_opset) {
|
||||
auto dummy_functor = ngraph::snippets::jitters_value {
|
||||
[](const std::shared_ptr<ngraph::Node>& n) { return std::make_shared<DummyEmitter>(); },
|
||||
[](const std::shared_ptr<ngraph::Node>& n) { return std::set<std::vector<element::Type>>{};}
|
||||
};
|
||||
|
||||
jitters[op::v0::Parameter::get_type_info_static()] = dummy_functor;
|
||||
jitters[op::v0::Constant::get_type_info_static()] = dummy_functor;
|
||||
jitters[op::v0::Result::get_type_info_static()] = dummy_functor;
|
||||
@@ -97,7 +99,9 @@ std::shared_ptr<ngraph::snippets::op::Subgraph> LoweringTests::getSubgraph(const
|
||||
|
||||
std::shared_ptr<ngraph::snippets::op::Subgraph> LoweringTests::getLoweredSubgraph(const std::shared_ptr<Model> &f,
|
||||
const ov::PartialShape& master_shape,
|
||||
ov::pass::Manager target_optimizations,
|
||||
ov::pass::Manager pre_dialect,
|
||||
ov::pass::Manager post_dialect,
|
||||
ov::pass::Manager post_precision,
|
||||
const std::shared_ptr<ngraph::snippets::Generator> generator) {
|
||||
auto subgraph = getTokenizedSubgraph(f);
|
||||
subgraph->set_generator(generator == nullptr ? std::make_shared<DummyGenerator>() : generator);
|
||||
@@ -119,7 +123,7 @@ std::shared_ptr<ngraph::snippets::op::Subgraph> LoweringTests::getLoweredSubgrap
|
||||
}
|
||||
body_rt_info["PluginShapesOverride"] = new_shapes;
|
||||
subgraph->set_tile_rank(2);
|
||||
subgraph->generate(target_optimizations);
|
||||
subgraph->generate(pre_dialect, post_precision, post_precision);
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "pass/precision_propagation.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "ngraph/pass/validate.hpp"
|
||||
#include "snippets/pass/propagate_precision.hpp"
|
||||
#include "snippets/op/convert_saturation.hpp"
|
||||
#include "common_test_utils/common_utils.hpp"
|
||||
#include "precision_propagation_function.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
namespace {
|
||||
|
||||
class DummyPrecisionPropagationTargetMachine : public DummyTargetMachine {
|
||||
public:
|
||||
DummyPrecisionPropagationTargetMachine(
|
||||
const std::set<std::vector<element::Type>>& op1_supported_precisions,
|
||||
const std::set<std::vector<element::Type>>& op2_supported_precisions)
|
||||
: DummyTargetMachine() {
|
||||
jitters[DummyAdd::get_type_info_static()] = ngraph::snippets::jitters_value {
|
||||
[](const std::shared_ptr<ngraph::Node>& n) { return std::make_shared<DummyEmitter>(); },
|
||||
[op1_supported_precisions](const std::shared_ptr<ngraph::Node>& n) { return op1_supported_precisions; }};
|
||||
jitters[op::v1::Maximum::get_type_info_static()] = ngraph::snippets::jitters_value{
|
||||
[](const std::shared_ptr<ngraph::Node>& n) { return std::make_shared<DummyEmitter>(); },
|
||||
[op2_supported_precisions](const std::shared_ptr<ngraph::Node>&n) { return op2_supported_precisions; }};
|
||||
|
||||
auto default_jitter = ngraph::snippets::jitters_value{
|
||||
[](const std::shared_ptr<ngraph::Node>& n) { return std::make_shared<DummyEmitter>(); },
|
||||
[](const std::shared_ptr<ngraph::Node>& n) { return std::set<std::vector<element::Type>>{};} };
|
||||
jitters[ngraph::snippets::op::ConvertSaturation::get_type_info_static()] = default_jitter;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string PrecisionPropagationTest::getTestCaseName(testing::TestParamInfo<PrecisionPropagationParams> obj) {
|
||||
std::pair<PartialShape, PartialShape> shapes;
|
||||
PrecisionPropagationParamsValues test_values;
|
||||
std::tie(shapes, test_values) = obj.param;
|
||||
|
||||
auto to_string = [](const std::set<std::vector<element::Type>>& precisions_pack) noexcept {
|
||||
std::ostringstream result;
|
||||
result << "{";
|
||||
for (const auto& precisions : precisions_pack) {
|
||||
result << CommonTestUtils::vec2str(precisions) << "_";
|
||||
}
|
||||
result << "}";
|
||||
return result.str();
|
||||
};
|
||||
|
||||
std::ostringstream result;
|
||||
result << "IN0_" << shapes.first << "_" << test_values.input_types[0] << "_"
|
||||
<< "IN1_" << shapes.second << "_" << test_values.input_types[1] << "_"
|
||||
<< "IN2_" << test_values.input_types[2]
|
||||
<< to_string(test_values.actual.op1_supported_precisions) << "_"
|
||||
<< to_string(test_values.actual.op2_supported_precisions) << "_"
|
||||
<< test_values.expected.convertion_before_op1.first << "_" << test_values.expected.convertion_before_op1.second << "_"
|
||||
<< test_values.expected.convertion_before_op2_1 << "_"
|
||||
<< test_values.expected.convertion_before_op2_2.first << "_" << test_values.expected.convertion_before_op2_2.second << "_"
|
||||
<< test_values.expected.convertion_after_op2 << "_";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
TEST_P(PrecisionPropagationTest, CompareFunctions) {
|
||||
disable_rt_info_check();
|
||||
|
||||
const auto param = GetParam();
|
||||
const auto shapes = std::get<0>(param);
|
||||
const auto test_values = std::get<1>(param);
|
||||
|
||||
const auto input_shapes = std::vector<PartialShape>({ shapes.first, shapes.second });
|
||||
PrecisionPropagationAddFunction function_stub(
|
||||
input_shapes,
|
||||
test_values.input_types[0],
|
||||
test_values.input_types[1],
|
||||
test_values.input_types[2],
|
||||
{
|
||||
test_values.actual.convertion_before_op1,
|
||||
test_values.actual.convertion_before_op2_1,
|
||||
test_values.actual.convertion_before_op2_2
|
||||
},
|
||||
{
|
||||
test_values.expected.convertion_before_op1,
|
||||
test_values.expected.convertion_before_op2_1,
|
||||
test_values.expected.convertion_before_op2_2,
|
||||
test_values.expected.convertion_after_op2
|
||||
});
|
||||
function = function_stub.getOriginal();
|
||||
|
||||
const auto target_machine = std::make_shared<DummyPrecisionPropagationTargetMachine>(
|
||||
test_values.actual.op1_supported_precisions,
|
||||
test_values.actual.op2_supported_precisions);
|
||||
|
||||
manager.register_pass<ngraph::snippets::pass::PropagatePrecision>(target_machine);
|
||||
|
||||
function_ref = function_stub.getReference();
|
||||
}
|
||||
|
||||
namespace PrecisionPropagationTestInstantiation {
|
||||
// clang-format off
|
||||
|
||||
std::vector<std::pair<PartialShape, PartialShape>> shapes {
|
||||
{{1, 3, 16, 16}, {1, 3, 16, 16}}
|
||||
};
|
||||
|
||||
std::vector<PrecisionPropagationParamsValues> test_cases {
|
||||
{
|
||||
{element::f32, element::f32, element::f32},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{element::f32, element::f32}},
|
||||
{{element::f32, element::f32}}
|
||||
},
|
||||
{}
|
||||
},
|
||||
// in: Parameter I8 => Op1 I32 => Convert I8 => Op1 I8 => Result
|
||||
// out: Parameter I8 => Add I32 => Convert I8 => Convert FP32 => Op1 FP32 => Result
|
||||
{
|
||||
{element::i8, element::i8, element::i8},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{element::i8, element::i8}},
|
||||
{{element::f32, element::f32}}
|
||||
},
|
||||
{
|
||||
{},
|
||||
element::i8,
|
||||
{element::f32, element::f32},
|
||||
{element::i8}
|
||||
}
|
||||
},
|
||||
{
|
||||
{element::i8, element::i8, element::i8},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{element::i8, element::i8}},
|
||||
{{element::i8, element::i8}}
|
||||
},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{element::i8, element::undefined},
|
||||
{}
|
||||
}
|
||||
},
|
||||
{
|
||||
{element::i8, element::i8, element::i8},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{element::i8, element::i8}},
|
||||
{{element::i32, element::i32}}
|
||||
},
|
||||
{
|
||||
{},
|
||||
{element::i8},
|
||||
{element::i32, element::i32},
|
||||
{element::i8}
|
||||
}
|
||||
},
|
||||
{
|
||||
{element::bf16, element::bf16, element::f32},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{element::i8, element::i8}
|
||||
},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{element::i32, element::i32}
|
||||
}
|
||||
},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
}
|
||||
},
|
||||
// propagate precision via operation #1
|
||||
{
|
||||
{element::bf16, element::bf16, element::f32},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{element::bf16, element::bf16}
|
||||
},
|
||||
{
|
||||
{element::f32, element::f32}
|
||||
}
|
||||
},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{element::f32, element::undefined},
|
||||
{}
|
||||
}
|
||||
},
|
||||
// propagate precision via operation #1
|
||||
{
|
||||
{element::bf16, element::bf16, element::bf16},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{},
|
||||
{element::undefined, element::f32},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{element::bf16, element::bf16}
|
||||
},
|
||||
{
|
||||
{element::f32, element::f32}
|
||||
}
|
||||
},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{element::f32, element::f32},
|
||||
{}
|
||||
}
|
||||
},
|
||||
// propagate precision via both operations
|
||||
{
|
||||
{element::bf16, element::bf16, element::bf16},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{},
|
||||
{element::undefined, element::f32},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{element::bf16, element::bf16}
|
||||
},
|
||||
{
|
||||
{element::f32, element::f32},
|
||||
{element::bf16, element::bf16}
|
||||
}
|
||||
},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{element::f32}
|
||||
}
|
||||
},
|
||||
{
|
||||
{element::bf16, element::bf16, element::bf16},
|
||||
{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{element::f32, element::f32}},
|
||||
{{element::f32, element::f32}}
|
||||
},
|
||||
{
|
||||
{{element::f32}, {element::f32}},
|
||||
{element::bf16},
|
||||
{{element::f32}, {element::f32}},
|
||||
{element::bf16}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
smoke_Snippets_PrecisionPropagationTest,
|
||||
PrecisionPropagationTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(shapes),
|
||||
::testing::ValuesIn(test_cases)),
|
||||
PrecisionPropagationTest::getTestCaseName);
|
||||
|
||||
// clang-format on
|
||||
} // namespace PrecisionPropagationTestInstantiation
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "snippets/pass/propagate_precision.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
class PrecisionPropagationConvertTest : public testing::Test {};
|
||||
|
||||
TEST_F(PrecisionPropagationConvertTest, smoke_Snippets_PrecisionPropagation_can_be_fused) {
|
||||
const std::set<std::pair<element::Type, element::Type>> precisions_set = {
|
||||
{element::u64, element::u64},
|
||||
{element::u64, element::u32},
|
||||
{element::u64, element::u16},
|
||||
{element::u64, element::u8},
|
||||
{element::u32, element::u32},
|
||||
{element::u32, element::u16},
|
||||
{element::u32, element::u8},
|
||||
{element::u16, element::u16},
|
||||
{element::u16, element::u8},
|
||||
{element::u8, element::u8},
|
||||
|
||||
{element::i64, element::i64},
|
||||
{element::i64, element::i32},
|
||||
{element::i64, element::i16},
|
||||
{element::i64, element::i8},
|
||||
{element::i32, element::i32},
|
||||
{element::i32, element::i16},
|
||||
{element::i32, element::i8},
|
||||
{element::i16, element::i16},
|
||||
{element::i16, element::i8},
|
||||
{element::i8, element::i8},
|
||||
|
||||
{element::f64, element::f64},
|
||||
{element::f64, element::f32},
|
||||
{element::f64, element::f16},
|
||||
{element::f32, element::f32},
|
||||
{element::f32, element::f16},
|
||||
{element::f16, element::f16},
|
||||
|
||||
{element::f32, element::bf16},
|
||||
{element::bf16, element::bf16},
|
||||
{element::f32, element::i8},
|
||||
{element::f16, element::i8},
|
||||
{element::bf16, element::i8},
|
||||
{element::f32, element::u8},
|
||||
{element::f16, element::u8},
|
||||
{element::bf16, element::u8}
|
||||
};
|
||||
|
||||
for (const auto& precisions : precisions_set) {
|
||||
ASSERT_TRUE(ngraph::snippets::pass::PropagatePrecision::can_be_fused(
|
||||
precisions.first,
|
||||
precisions.second)) << precisions.second << " can replace " << precisions.first;
|
||||
|
||||
if (precisions.first == precisions.second) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT_FALSE(ngraph::snippets::pass::PropagatePrecision::can_be_fused(
|
||||
precisions.second,
|
||||
precisions.first)) << precisions.second << " can not replace " << precisions.first;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PrecisionPropagationConvertTest, smoke_Snippets_PrecisionPropagation_can_not_be_fused) {
|
||||
const std::set<std::pair<element::Type, element::Type>> precisions_set = {
|
||||
{element::i64, element::f32},
|
||||
{element::i64, element::f16},
|
||||
{element::i64, element::bf16},
|
||||
|
||||
{element::i32, element::f32},
|
||||
{element::i32, element::f16},
|
||||
{element::i32, element::bf16},
|
||||
|
||||
{element::i16, element::f16},
|
||||
{element::i16, element::bf16},
|
||||
|
||||
{element::u64, element::f32},
|
||||
{element::u64, element::f16},
|
||||
{element::u64, element::bf16},
|
||||
|
||||
{element::u32, element::f32},
|
||||
{element::u32, element::f16},
|
||||
{element::u32, element::bf16},
|
||||
|
||||
{element::u16, element::f16},
|
||||
{element::u16, element::bf16}
|
||||
};
|
||||
|
||||
for (const auto& precisions : precisions_set) {
|
||||
ASSERT_FALSE(ngraph::snippets::pass::PropagatePrecision::can_be_fused(
|
||||
precisions.first,
|
||||
precisions.second)) << precisions.second << " can not replace " << precisions.first;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PrecisionPropagationConvertTest, smoke_Snippets_PrecisionPropagation_can_be_removed) {
|
||||
const std::set<std::tuple<element::Type, element::Type, element::Type>> precisions_set = {
|
||||
{element::u64, element::u64, element::u64},
|
||||
{element::u32, element::u64, element::u32},
|
||||
{element::u16, element::u64, element::u16},
|
||||
{element::u8, element::u64, element::u8},
|
||||
{element::u32, element::u32, element::u32},
|
||||
{element::u16, element::u32, element::u16},
|
||||
{element::u8, element::u32, element::u8},
|
||||
{element::u16, element::u16, element::u16},
|
||||
{element::u8, element::u16, element::u8},
|
||||
{element::u8, element::u8, element::u8},
|
||||
|
||||
{element::i64, element::i64, element::i64},
|
||||
{element::i32, element::i64, element::i32},
|
||||
{element::i16, element::i64, element::i16},
|
||||
{element::i8, element::i64, element::i8},
|
||||
{element::i32, element::i32, element::i32},
|
||||
{element::i16, element::i32, element::i16},
|
||||
{element::i8, element::i32, element::i8},
|
||||
{element::i16, element::i16, element::i16},
|
||||
{element::i8, element::i16, element::i8},
|
||||
{element::i8, element::i8, element::i8},
|
||||
|
||||
{element::f64, element::f64, element::f64},
|
||||
{element::f32, element::f64, element::f32},
|
||||
{element::f16, element::f64, element::f16},
|
||||
{element::f32, element::f32, element::f32},
|
||||
{element::f16, element::f16, element::f16},
|
||||
|
||||
{element::bf16, element::f32, element::bf16},
|
||||
{element::bf16, element::bf16, element::bf16},
|
||||
};
|
||||
|
||||
for (const auto& precisions : precisions_set) {
|
||||
const auto actual_before = std::get<0>(precisions);
|
||||
const auto actual_after = std::get<1>(precisions);
|
||||
const auto required_after = std::get<2>(precisions);
|
||||
ASSERT_TRUE(ngraph::snippets::pass::PropagatePrecision::can_be_removed(
|
||||
actual_before,
|
||||
actual_after,
|
||||
required_after)) << "can_be_removed: " << actual_before << " => " << actual_after << " => " << required_after;
|
||||
|
||||
if ((actual_before == actual_after) && (actual_before == required_after)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "snippets/pass/propagate_precision.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
|
||||
class PrecisionPropagationGetPrecisionsTest : public testing::Test {};
|
||||
|
||||
TEST_F(PrecisionPropagationGetPrecisionsTest, empty) {
|
||||
ASSERT_EQ(std::vector<element::Type>{}, ngraph::snippets::pass::PropagatePrecision::get_precisions({}, {}));
|
||||
}
|
||||
|
||||
TEST_F(PrecisionPropagationGetPrecisionsTest, selected) {
|
||||
ASSERT_EQ(
|
||||
std::vector<element::Type>({element::f32, element::f32}),
|
||||
ngraph::snippets::pass::PropagatePrecision::get_precisions(
|
||||
{ element::f32, element::f32 },
|
||||
{
|
||||
{element::bf16, element::bf16},
|
||||
{element::f32, element::f32},
|
||||
{element::i8, element::i8},
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(PrecisionPropagationGetPrecisionsTest, first) {
|
||||
ASSERT_EQ(
|
||||
std::vector<element::Type>({ element::bf16, element::bf16 }),
|
||||
ngraph::snippets::pass::PropagatePrecision::get_precisions(
|
||||
{ element::i32, element::i32 },
|
||||
{
|
||||
{element::bf16, element::bf16},
|
||||
{element::f32, element::f32},
|
||||
{element::i8, element::i8},
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -503,7 +503,9 @@ string pass::VisualizeTree::get_node_name(shared_ptr<Node> node) {
|
||||
if (node->get_friendly_name() != node->get_name()) {
|
||||
rc += "\\n" + (nvtmn ? string("name: ") : "") + node->get_name();
|
||||
}
|
||||
rc += "\\n" + (nvtmn ? string("type_name: ") : "") + std::string(node->get_type_name());
|
||||
const auto type_info = node->get_type_info();
|
||||
rc += "\\n" + (nvtmn ? string("type_name: ") : "") + std::string(type_info.version_id) +
|
||||
"::" + std::string(type_info.name);
|
||||
|
||||
static const bool nvttn = getenv_bool("OV_VISUALIZE_TREE_TENSORS_NAME");
|
||||
if (nvttn) {
|
||||
|
||||
@@ -26,8 +26,14 @@
|
||||
using namespace std;
|
||||
using namespace ngraph::snippets;
|
||||
|
||||
#define CREATE_EMITTER(e_type) [this](const std::shared_ptr<ngraph::Node>& n) \
|
||||
-> std::shared_ptr<ngraph::snippets::Emitter> {return std::make_shared<e_type>(h.get(), isa, n);};
|
||||
#define CREATE_EMITTER(e_type) { \
|
||||
[this](const std::shared_ptr<ngraph::Node>& n) -> std::shared_ptr<ngraph::snippets::Emitter> { \
|
||||
return std::make_shared<e_type>(h.get(), isa, n); \
|
||||
}, \
|
||||
[](const std::shared_ptr<ngraph::Node>& n) -> std::set<std::vector<element::Type>> { \
|
||||
return e_type::get_supported_precisions(n); \
|
||||
} \
|
||||
};
|
||||
|
||||
class jit_snippet : public dnnl::impl::cpu::x64::jit_generator {
|
||||
public:
|
||||
|
||||
@@ -13,6 +13,10 @@ using namespace Xbyak;
|
||||
namespace ov {
|
||||
namespace intel_cpu {
|
||||
|
||||
std::set<std::vector<element::Type>> jit_dnnl_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
jit_dnnl_emitter::jit_dnnl_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr<ngraph::Node>& node, InferenceEngine::Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ public:
|
||||
|
||||
void emit_impl(const std::vector<size_t> &in_idxs, const std::vector<size_t> &out_idxs) const override {};
|
||||
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
protected:
|
||||
jit_dnnl_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
dnnl_alg_kind_t algKind, float inpAlpha, float inpBeta,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include "jit_eltwise_emitters.hpp"
|
||||
#include "ie_ngraph_utils.hpp"
|
||||
|
||||
using namespace InferenceEngine;
|
||||
using namespace dnnl::impl::utils;
|
||||
@@ -16,9 +17,26 @@ using namespace Xbyak;
|
||||
namespace ov {
|
||||
namespace intel_cpu {
|
||||
|
||||
namespace {
|
||||
InferenceEngine::Precision get_arithmetic_binary_exec_precision(const std::shared_ptr<ov::Node>& n) {
|
||||
std::vector<InferenceEngine::Precision> input_precisions;
|
||||
for (const auto& input : n->inputs()) {
|
||||
input_precisions.push_back(
|
||||
InferenceEngine::details::convertPrecision(input.get_source_output().get_element_type()));
|
||||
}
|
||||
|
||||
assert(std::all_of(
|
||||
input_precisions.begin(),
|
||||
input_precisions.end(),
|
||||
[&input_precisions](const InferenceEngine::Precision& precision) {return precision == input_precisions[0]; }));
|
||||
|
||||
return input_precisions[0];
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/// ADD ///
|
||||
jit_add_emitter::jit_add_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_add_emitter::jit_add_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node)
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_add_emitter::jit_add_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -59,13 +77,13 @@ void jit_add_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, const std
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_add_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_add_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// MUL_ADD ///
|
||||
jit_mul_add_emitter::jit_mul_add_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_mul_add_emitter::jit_mul_add_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node)
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_mul_add_emitter::jit_mul_add_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -150,13 +168,13 @@ size_t jit_mul_add_emitter::aux_vecs_count() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::set<Precision> jit_mul_add_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_mul_add_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32, element::f32}, {element::i32, element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// SUB ///
|
||||
jit_subtract_emitter::jit_subtract_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_subtract_emitter::jit_subtract_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node)
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_subtract_emitter::jit_subtract_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -197,13 +215,13 @@ void jit_subtract_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, cons
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_subtract_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_subtract_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// MULTIPLY ///
|
||||
jit_multiply_emitter::jit_multiply_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_multiply_emitter::jit_multiply_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node)
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_multiply_emitter::jit_multiply_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -244,13 +262,13 @@ void jit_multiply_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, cons
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_multiply_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_multiply_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// DIVIDE ///
|
||||
jit_divide_emitter::jit_divide_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_divide_emitter::jit_divide_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -305,8 +323,8 @@ void jit_divide_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, const
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_divide_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_divide_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
size_t jit_divide_emitter::aux_vecs_count() const {
|
||||
@@ -321,7 +339,11 @@ jit_floor_emitter::jit_floor_emitter(x64::jit_generator *host, x64::cpu_isa_t ho
|
||||
|
||||
size_t jit_floor_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
void jit_floor_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_floor_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_floor_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -344,11 +366,15 @@ void jit_floor_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, const s
|
||||
/// CEILING ///
|
||||
jit_ceiling_emitter::jit_ceiling_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_ceiling_emitter::jit_ceiling_emitter(x64::jit_generator* host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
jit_ceiling_emitter::jit_ceiling_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
size_t jit_ceiling_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
std::set<std::vector<element::Type>> jit_ceiling_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_ceiling_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs,
|
||||
const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
@@ -378,7 +404,11 @@ jit_floor_mod_emitter::jit_floor_mod_emitter(x64::jit_generator *host, x64::cpu_
|
||||
|
||||
size_t jit_floor_mod_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_floor_mod_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_floor_mod_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_floor_mod_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -428,7 +458,11 @@ jit_mod_emitter::jit_mod_emitter(x64::jit_generator *host, x64::cpu_isa_t host_i
|
||||
|
||||
size_t jit_mod_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_mod_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_mod_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_mod_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -471,8 +505,8 @@ size_t jit_mod_emitter::aux_vecs_count() const {
|
||||
}
|
||||
|
||||
/// MAXIMUM ///
|
||||
jit_maximum_emitter::jit_maximum_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_maximum_emitter::jit_maximum_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node)
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_maximum_emitter::jit_maximum_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -514,13 +548,13 @@ void jit_maximum_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, const
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_maximum_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_maximum_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// MINIMUM ///
|
||||
jit_minimum_emitter::jit_minimum_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, node, exec_prc) {}
|
||||
jit_minimum_emitter::jit_minimum_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& node)
|
||||
: jit_emitter(host, host_isa, node, get_arithmetic_binary_exec_precision(node)) {}
|
||||
jit_minimum_emitter::jit_minimum_emitter(x64::jit_generator *host, x64::cpu_isa_t host_isa, Precision exec_prc)
|
||||
: jit_emitter(host, host_isa, exec_prc) {}
|
||||
|
||||
@@ -562,8 +596,8 @@ void jit_minimum_emitter::emit_isa(const std::vector<size_t> &in_vec_idxs, const
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_minimum_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_minimum_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// SQUARED_DIFFERENCE ///
|
||||
@@ -617,8 +651,8 @@ void jit_squared_difference_emitter::emit_isa(const std::vector<size_t> &in_vec_
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Precision> jit_squared_difference_emitter::get_supported_precisions() {
|
||||
return {Precision::FP32, Precision::I32};
|
||||
std::set<std::vector<element::Type>> jit_squared_difference_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}, {element::i32, element::i32}};
|
||||
}
|
||||
|
||||
/// POWER_DYNAMIC ///
|
||||
@@ -630,7 +664,11 @@ jit_power_dynamic_emitter::jit_power_dynamic_emitter(x64::jit_generator *host, x
|
||||
|
||||
size_t jit_power_dynamic_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_power_dynamic_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_power_dynamic_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_power_dynamic_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -741,7 +779,11 @@ jit_equal_emitter::jit_equal_emitter(x64::jit_generator *host, x64::cpu_isa_t ho
|
||||
|
||||
size_t jit_equal_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_equal_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_equal_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_equal_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -800,7 +842,11 @@ jit_not_equal_emitter::jit_not_equal_emitter(x64::jit_generator *host, x64::cpu_
|
||||
|
||||
size_t jit_not_equal_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_not_equal_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_not_equal_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_not_equal_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -859,7 +905,11 @@ jit_greater_emitter::jit_greater_emitter(x64::jit_generator *host, x64::cpu_isa_
|
||||
|
||||
size_t jit_greater_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_greater_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_greater_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_greater_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -919,7 +969,11 @@ jit_greater_equal_emitter::jit_greater_equal_emitter(x64::jit_generator *host, x
|
||||
|
||||
size_t jit_greater_equal_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_greater_equal_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_greater_equal_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_greater_equal_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -978,7 +1032,11 @@ jit_less_emitter::jit_less_emitter(x64::jit_generator *host, x64::cpu_isa_t host
|
||||
|
||||
size_t jit_less_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_less_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_less_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_less_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1037,7 +1095,11 @@ jit_less_equal_emitter::jit_less_equal_emitter(x64::jit_generator *host, x64::cp
|
||||
|
||||
size_t jit_less_equal_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_less_equal_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_less_equal_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_less_equal_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1097,7 +1159,11 @@ jit_logical_and_emitter::jit_logical_and_emitter(x64::jit_generator *host, x64::
|
||||
|
||||
size_t jit_logical_and_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_logical_and_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_logical_and_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_logical_and_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1177,7 +1243,11 @@ jit_logical_or_emitter::jit_logical_or_emitter(x64::jit_generator *host, x64::cp
|
||||
|
||||
size_t jit_logical_or_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_logical_or_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_logical_or_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_logical_or_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1256,7 +1326,11 @@ jit_logical_xor_emitter::jit_logical_xor_emitter(x64::jit_generator *host, x64::
|
||||
|
||||
size_t jit_logical_xor_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_logical_xor_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_logical_xor_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_logical_xor_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1335,7 +1409,11 @@ jit_logical_not_emitter::jit_logical_not_emitter(x64::jit_generator *host, x64::
|
||||
|
||||
size_t jit_logical_not_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
void jit_logical_not_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_logical_not_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_logical_not_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1405,7 +1483,11 @@ jit_power_static_emitter::jit_power_static_emitter(x64::jit_generator *host, x64
|
||||
|
||||
size_t jit_power_static_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
void jit_power_static_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_power_static_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_power_static_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1579,7 +1661,11 @@ jit_prelu_emitter::jit_prelu_emitter(x64::jit_generator *host, x64::cpu_isa_t ho
|
||||
}
|
||||
size_t jit_prelu_emitter::get_inputs_num() const { return 2; }
|
||||
|
||||
void jit_prelu_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_prelu_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
void jit_prelu_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1634,7 +1720,11 @@ jit_sqrt_emitter::jit_sqrt_emitter(x64::jit_generator *host, x64::cpu_isa_t host
|
||||
|
||||
size_t jit_sqrt_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
void jit_sqrt_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_sqrt_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_sqrt_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1661,7 +1751,11 @@ jit_negative_emitter::jit_negative_emitter(x64::jit_generator *host, x64::cpu_is
|
||||
|
||||
size_t jit_negative_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
void jit_negative_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_negative_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_negative_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -1695,6 +1789,10 @@ jit_erf_emitter::jit_erf_emitter(x64::jit_generator *host, x64::cpu_isa_t host_i
|
||||
|
||||
size_t jit_erf_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
std::set<std::vector<element::Type>> jit_erf_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_erf_emitter::emit_impl(
|
||||
const std::vector<size_t> &in_vec_idxs,
|
||||
const std::vector<size_t> &out_vec_idxs) const {
|
||||
@@ -1875,7 +1973,11 @@ jit_soft_sign_emitter::jit_soft_sign_emitter(x64::jit_generator *host, x64::cpu_
|
||||
|
||||
size_t jit_soft_sign_emitter::get_inputs_num() const { return 1; }
|
||||
|
||||
void jit_soft_sign_emitter::emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const {
|
||||
std::set<std::vector<element::Type>> jit_soft_sign_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
void jit_soft_sign_emitter::emit_impl(const std::vector<size_t>& in_vec_idxs, const std::vector<size_t>& out_vec_idxs) const {
|
||||
if (host_isa_ == x64::sse41) {
|
||||
emit_isa<x64::sse41>(in_vec_idxs, out_vec_idxs);
|
||||
} else if (host_isa_ == x64::avx2) {
|
||||
@@ -2086,6 +2188,10 @@ jit_select_emitter::jit_select_emitter(x64::jit_generator *host, x64::cpu_isa_t
|
||||
|
||||
size_t jit_select_emitter::get_inputs_num() const { return 3; }
|
||||
|
||||
std::set<std::vector<element::Type>> jit_select_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {{element::f32, element::f32, element::f32}};
|
||||
}
|
||||
|
||||
size_t jit_select_emitter::aux_vecs_count() const {
|
||||
if (host_isa_ == x64::avx512_core)
|
||||
return 0;
|
||||
|
||||
@@ -13,11 +13,10 @@ class jit_add_emitter : public jit_emitter {
|
||||
public:
|
||||
jit_add_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_add_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_add_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -30,11 +29,10 @@ class jit_mul_add_emitter : public jit_emitter {
|
||||
public:
|
||||
jit_mul_add_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_mul_add_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_mul_add_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -50,11 +48,10 @@ class jit_subtract_emitter : public jit_emitter {
|
||||
public:
|
||||
jit_subtract_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_subtract_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_subtract_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -68,11 +65,10 @@ class jit_multiply_emitter : public jit_emitter {
|
||||
public:
|
||||
jit_multiply_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_multiply_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_multiply_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -90,7 +86,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -108,6 +104,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -124,6 +121,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -140,6 +138,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -158,6 +157,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -172,11 +172,10 @@ class jit_maximum_emitter : public jit_emitter {
|
||||
public:
|
||||
jit_maximum_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_maximum_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_maximum_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -190,11 +189,10 @@ class jit_minimum_emitter : public jit_emitter {
|
||||
public:
|
||||
jit_minimum_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_minimum_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n,
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
jit_minimum_emitter(dnnl::impl::cpu::x64::jit_generator *host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -213,7 +211,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -231,6 +229,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -248,6 +247,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -268,6 +268,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -288,6 +289,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -308,6 +310,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -328,6 +331,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -349,6 +353,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -369,6 +374,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -389,6 +395,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -409,6 +416,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -428,6 +436,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -448,6 +457,8 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -471,6 +482,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -489,6 +501,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -503,6 +516,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t>& in, const std::vector<size_t>& out) const override;
|
||||
@@ -520,6 +534,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(
|
||||
@@ -541,6 +556,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t> &in_vec_idxs, const std::vector<size_t> &out_vec_idxs) const override;
|
||||
@@ -563,6 +579,9 @@ public:
|
||||
}
|
||||
|
||||
size_t get_inputs_num() const override { return 1; };
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t aux_gprs_count() const override { return (entry_map_.empty() ? 0 : 1) + 1; }
|
||||
@@ -588,6 +607,9 @@ public:
|
||||
}
|
||||
|
||||
size_t get_inputs_num() const override { return 1; };
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t aux_gprs_count() const override { return (entry_map_.empty() ? 0 : 1) + 1; }
|
||||
@@ -615,6 +637,9 @@ public:
|
||||
}
|
||||
|
||||
size_t get_inputs_num() const override { return 1; }
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t aux_gprs_count() const override { return (entry_map_.empty() ? 0 : 1) + 1; }
|
||||
@@ -635,6 +660,7 @@ public:
|
||||
InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32);
|
||||
|
||||
size_t get_inputs_num() const override;
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
size_t aux_vecs_count() const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
//
|
||||
|
||||
#include "jit_emitter.hpp"
|
||||
#include "utils/general_utils.h"
|
||||
#include <vector>
|
||||
#include "utils/general_utils.h"
|
||||
|
||||
using namespace dnnl::impl::cpu;
|
||||
using namespace dnnl::impl;
|
||||
@@ -55,8 +55,8 @@ size_t jit_emitter::aux_gprs_count() const {
|
||||
return entry_map_.empty() ? 0 : 1;
|
||||
}
|
||||
|
||||
std::set<InferenceEngine::Precision> jit_emitter::get_supported_precisions() {
|
||||
return {InferenceEngine::Precision::FP32};
|
||||
std::set<std::vector<element::Type>> jit_emitter::get_supported_precisions(const std::shared_ptr<ngraph::Node>& node) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void jit_emitter::emitter_preamble(const std::vector<size_t> &in_idxs, const std::vector<size_t> &out_idxs,
|
||||
|
||||
@@ -49,7 +49,13 @@ public:
|
||||
virtual size_t get_inputs_num() const = 0;
|
||||
virtual size_t aux_vecs_count() const;
|
||||
emitter_in_out_map get_in_out_type() const;
|
||||
static std::set<InferenceEngine::Precision> get_supported_precisions();
|
||||
|
||||
/**
|
||||
* @brief Returns supported precisions.
|
||||
* Precisions are ordered, the first bigger bitness precision with the same type will be selected.
|
||||
* Empty collection means the emitter supports any input precisions.
|
||||
*/
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr);
|
||||
|
||||
protected:
|
||||
virtual size_t aux_gprs_count() const;
|
||||
|
||||
@@ -479,7 +479,20 @@ void BroadcastMoveEmitter::emit_isa(const std::vector<size_t> &in, const std::ve
|
||||
|
||||
ScalarEmitter::ScalarEmitter(dnnl::impl::cpu::x64::jit_generator* h, dnnl::impl::cpu::x64::cpu_isa_t isa,
|
||||
const std::shared_ptr<ov::Node>& n) : jit_emitter(h, isa, n) {
|
||||
value = dnnl::impl::cpu::x64::float2int(ov::as_type_ptr<ngraph::snippets::op::Scalar>(n)->cast_vector<float>()[0]);
|
||||
const auto precision = n->get_output_element_type(0);
|
||||
switch (precision) {
|
||||
case element::i32: {
|
||||
value = ov::as_type_ptr<ov::op::v0::Constant>(n)->cast_vector<int32_t>()[0];
|
||||
break;
|
||||
}
|
||||
case element::f32: {
|
||||
value = dnnl::impl::cpu::x64::float2int(ov::as_type_ptr<ov::op::v0::Constant>(n)->cast_vector<float>()[0]);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
IE_THROW() << "Scalar emitter doesn't support " << precision;
|
||||
}
|
||||
}
|
||||
push_arg_entry_of("scalar", value, true);
|
||||
prepare_table();
|
||||
}
|
||||
|
||||
@@ -322,6 +322,9 @@ public:
|
||||
BrgemmEmitter(dnnl::impl::cpu::x64::jit_generator* h, dnnl::impl::cpu::x64::cpu_isa_t isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override {return 2;}
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr) {
|
||||
return {{element::f32, element::f32}};
|
||||
}
|
||||
|
||||
private:
|
||||
void emit_impl(const std::vector<size_t>& in,
|
||||
@@ -369,6 +372,9 @@ public:
|
||||
HorizonMaxEmitter(dnnl::impl::cpu::x64::jit_generator* h, dnnl::impl::cpu::x64::cpu_isa_t isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override {return 1;}
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t aux_gprs_count() const override {return 1;}
|
||||
@@ -387,6 +393,9 @@ public:
|
||||
HorizonSumEmitter(dnnl::impl::cpu::x64::jit_generator* h, dnnl::impl::cpu::x64::cpu_isa_t isa, const std::shared_ptr<ov::Node>& n);
|
||||
|
||||
size_t get_inputs_num() const override {return 1;}
|
||||
static std::set<std::vector<element::Type>> get_supported_precisions(const std::shared_ptr<ngraph::Node>& node = nullptr) {
|
||||
return {{element::f32}};
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t aux_gprs_count() const override {return 1;}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "cpu_types.h"
|
||||
#include "utils/bfloat16.hpp"
|
||||
#include "ie_ngraph_utils.hpp"
|
||||
#include <cpu/x64/injectors/jit_uni_quantization_injector.hpp>
|
||||
#include <cpu/ref_eltwise.hpp>
|
||||
|
||||
@@ -58,7 +59,7 @@ namespace {
|
||||
|
||||
template<typename T>
|
||||
struct SupportedPrecisions {
|
||||
void operator()(std::set<Precision> &precisions) {
|
||||
void operator()(std::set<std::vector<element::Type>> &precisions) {
|
||||
precisions = T::get_supported_precisions();
|
||||
}
|
||||
};
|
||||
@@ -105,7 +106,7 @@ struct EltwiseEmitter<jit_is_inf_emitter> {
|
||||
/**
|
||||
* Implements Eltwise shape inference algorithm. The algorithm is based on broadcasting all the input shapes
|
||||
* according to the NUMPY broadcast rule. This implementation is more lightweight than the ngraph one.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class EltwiseShapeInfer : public ShapeInferEmptyPads {
|
||||
public:
|
||||
@@ -176,10 +177,31 @@ struct jit_uni_eltwise_generic : public jit_uni_eltwise_kernel, public jit_gener
|
||||
void generate() override {
|
||||
Precision exec_prc = Precision::UNSPECIFIED;
|
||||
|
||||
std::set<Precision> supported_precision_intersection = get_supported_precisions(eltwise_data_.front().algo);
|
||||
std::set<std::vector<element::Type>> supported_precision_intersection = get_supported_precisions(eltwise_data_.front().algo);
|
||||
|
||||
// for element-wise operations all inputs must to have the same precisions
|
||||
assert(std::all_of(
|
||||
supported_precision_intersection.begin(),
|
||||
supported_precision_intersection.end(),
|
||||
[&supported_precision_intersection](const std::vector<element::Type>& precisions) {
|
||||
return std::all_of(
|
||||
precisions.begin(),
|
||||
precisions.end(),
|
||||
[&precisions](const element::Type precision) { return precision == precisions[0]; });
|
||||
}));
|
||||
|
||||
for (size_t i = 1; i < eltwise_data_.size(); ++i) {
|
||||
std::set<Precision> prcs = get_supported_precisions(eltwise_data_[i].algo);
|
||||
std::set<Precision> prcs_intersect = {};
|
||||
std::set<std::vector<element::Type>> prcs = get_supported_precisions(eltwise_data_[i].algo);
|
||||
std::set<std::vector<element::Type>> prcs_intersect = {};
|
||||
|
||||
// to support previous functionality
|
||||
if (!std::all_of(
|
||||
prcs.begin(),
|
||||
prcs.end(),
|
||||
[&supported_precision_intersection](const std::vector<element::Type>& types) {
|
||||
return types.size() == supported_precision_intersection.size(); })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set_intersection(supported_precision_intersection.begin(), supported_precision_intersection.end(),
|
||||
prcs.begin(), prcs.end(), std::inserter(prcs_intersect, prcs_intersect.begin()));
|
||||
@@ -187,19 +209,22 @@ struct jit_uni_eltwise_generic : public jit_uni_eltwise_kernel, public jit_gener
|
||||
supported_precision_intersection = prcs_intersect;
|
||||
}
|
||||
|
||||
static const Precision exec_precisions_priority[] = {
|
||||
Precision::U8,
|
||||
Precision::I8,
|
||||
Precision::U16,
|
||||
Precision::I16,
|
||||
Precision::BF16,
|
||||
Precision::I32,
|
||||
Precision::FP32
|
||||
static const element::Type exec_precisions_priority[] = {
|
||||
element::u8,
|
||||
element::i8,
|
||||
element::u16,
|
||||
element::i16,
|
||||
element::bf16,
|
||||
element::i32,
|
||||
element::f32
|
||||
};
|
||||
|
||||
for (auto prc : exec_precisions_priority) {
|
||||
if (std::find(supported_precision_intersection.begin(), supported_precision_intersection.end(), prc) != supported_precision_intersection.end()) {
|
||||
exec_prc = prc;
|
||||
for (const auto prc : exec_precisions_priority) {
|
||||
if (std::any_of(
|
||||
supported_precision_intersection.begin(),
|
||||
supported_precision_intersection.end(),
|
||||
[&prc](const std::vector<element::Type>& precisions) { return std::find(precisions.begin(), precisions.end(), prc) != precisions.end(); })) {
|
||||
exec_prc = InferenceEngine::details::convertPrecision(prc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -482,8 +507,8 @@ private:
|
||||
const std::vector<ov::intel_cpu::Type>& ops_list_;
|
||||
const dnnl::post_ops& post_ops_;
|
||||
|
||||
std::set<Precision> get_supported_precisions(Algorithm algo) {
|
||||
std::set<Precision> precisions;
|
||||
std::set<std::vector<element::Type>> get_supported_precisions(Algorithm algo) {
|
||||
std::set<std::vector<element::Type>> precisions;
|
||||
|
||||
OV_SWITCH(intel_cpu, SupportedPrecisions, precisions, algo,
|
||||
OV_CASE(Algorithm::EltwiseRelu, jit_dnnl_aux_emitter),
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "utils/cpu_utils.hpp"
|
||||
#include "snippets_transformations/fuse_load_store_and_convert.hpp"
|
||||
#include "snippets_transformations/mul_add_to_fma.hpp"
|
||||
#include "snippets_transformations/remove_converts.hpp"
|
||||
#include "ngraph_transformations/convert_to_swish_cpu.hpp"
|
||||
|
||||
using namespace InferenceEngine;
|
||||
@@ -39,7 +40,7 @@ namespace node {
|
||||
namespace {
|
||||
|
||||
/* This class implementation is a temporal WA
|
||||
TODO: revise the implementation to remove the node reference*/
|
||||
TODO: revise the implementation to remove the node reference*/
|
||||
class SnippetShapeInfer : public ShapeInferEmptyPads {
|
||||
public:
|
||||
SnippetShapeInfer(Snippet* node) : m_node(node) {}
|
||||
@@ -531,28 +532,36 @@ bool Snippet::created() const {
|
||||
}
|
||||
|
||||
void Snippet::generate(const jit_snippets_compile_args* jcp) {
|
||||
ov::pass::Manager optManager;
|
||||
optManager.register_pass<ov::intel_cpu::pass::FuseLoadConvert>();
|
||||
optManager.register_pass<ov::intel_cpu::pass::FuseStoreConvert>();
|
||||
optManager.register_pass<ConvertToSwishCPU>();
|
||||
optManager.register_pass<ov::intel_cpu::pass::MulAddToFMA>();
|
||||
ov::pass::Manager pre_dialect;
|
||||
pre_dialect.register_pass<ConvertToSwishCPU>();
|
||||
|
||||
ov::pass::Manager post_dialect;
|
||||
|
||||
ov::pass::Manager post_precision;
|
||||
post_precision.register_pass<ov::intel_cpu::pass::RemoveConverts>();
|
||||
post_precision.register_pass<ov::intel_cpu::pass::FuseLoadConvert>();
|
||||
post_precision.register_pass<ov::intel_cpu::pass::FuseStoreConvert>();
|
||||
// LoadConvert uses Load emitter that support conversion from any type to only f32
|
||||
optManager.get_pass_config()->set_callback<ov::intel_cpu::pass::FuseLoadConvert>(
|
||||
post_precision.get_pass_config()->set_callback<ov::intel_cpu::pass::FuseLoadConvert>(
|
||||
[](const std::shared_ptr<const ov::Node>& n) -> bool {
|
||||
if (const auto& convert = std::dynamic_pointer_cast<const ov::op::v0::Convert>(n))
|
||||
return convert->get_destination_type() != ov::element::f32;
|
||||
return true;
|
||||
});
|
||||
|
||||
// StoreConvert uses Store emitter that support conversion from only f32 to any types
|
||||
optManager.get_pass_config()->set_callback<ov::intel_cpu::pass::FuseStoreConvert>(
|
||||
post_precision.get_pass_config()->set_callback<ov::intel_cpu::pass::FuseStoreConvert>(
|
||||
[](const std::shared_ptr<const ov::Node>& n) -> bool {
|
||||
if (const auto& convert = std::dynamic_pointer_cast<const ov::op::v0::Convert>(n))
|
||||
return convert->get_input_element_type(0) != ov::element::f32;
|
||||
return true;
|
||||
});
|
||||
schedule = snippet->generate(optManager, reinterpret_cast<const void*>(jcp));
|
||||
post_precision.register_pass<ov::intel_cpu::pass::MulAddToFMA>();
|
||||
|
||||
schedule = snippet->generate(
|
||||
pre_dialect,
|
||||
post_dialect,
|
||||
post_precision,
|
||||
reinterpret_cast<const void*>(jcp));
|
||||
}
|
||||
|
||||
void Snippet::update_ptrs(jit_snippets_call_args& call_args) {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "remove_converts.hpp"
|
||||
|
||||
#include "snippets/itt.hpp"
|
||||
#include "ngraph/opsets/opset1.hpp"
|
||||
#include "ngraph/rt_info.hpp"
|
||||
#include "ngraph/pattern/op/wrap_type.hpp"
|
||||
|
||||
#include "snippets/op/convert_saturation.hpp"
|
||||
|
||||
ov::intel_cpu::pass::RemoveConverts::RemoveConverts() {
|
||||
MATCHER_SCOPE(RemoveConverts);
|
||||
auto parent_convert_wrap = ngraph::pattern::wrap_type<ngraph::snippets::op::ConvertSaturation>();
|
||||
auto child_convert_wrap = ngraph::pattern::wrap_type<ngraph::snippets::op::ConvertSaturation>({ parent_convert_wrap });
|
||||
|
||||
auto callback = [=](ngraph::pattern::Matcher& m) {
|
||||
OV_ITT_SCOPED_TASK(ngraph::pass::itt::domains::SnippetsTransform, "ov::intel_cpu::pass::RemoveConverts")
|
||||
const auto& pm = m.get_pattern_value_map();
|
||||
const auto parent_convert = pm.at(parent_convert_wrap).get_node_shared_ptr();
|
||||
const auto child_convert = pm.at(child_convert_wrap).get_node_shared_ptr();
|
||||
if (
|
||||
(parent_convert->get_input_element_type(0) != element::f32) ||
|
||||
(parent_convert->get_output_target_inputs(0).size() != 1ull) ||
|
||||
(parent_convert->get_output_element_type(0) != element::bf16) ||
|
||||
(child_convert->get_output_element_type(0) != element::f32)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
replace_output_update_name(child_convert->output(0), parent_convert->get_input_source_output(0));
|
||||
return true;
|
||||
};
|
||||
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(child_convert_wrap, matcher_name);
|
||||
register_matcher(m, callback);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/pass/graph_rewrite.hpp"
|
||||
#include "ngraph/pattern/matcher.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace intel_cpu {
|
||||
namespace pass {
|
||||
|
||||
/**
|
||||
* @interface RemoveConverts
|
||||
* @brief Remove sequence of two ConvertSaturation operations for specific precisions: FP32 => BF16 => FP32
|
||||
* @ingroup snippets
|
||||
*/
|
||||
class RemoveConverts : public ngraph::pass::MatcherPass {
|
||||
public:
|
||||
OPENVINO_RTTI("RemoveConverts", "0");
|
||||
RemoveConverts();
|
||||
};
|
||||
|
||||
} // namespace pass
|
||||
} // namespace intel_cpu
|
||||
} // namespace ov
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "snippets/check_broadcast.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<ov::element::Type> input_types = {
|
||||
// TODO: 105804
|
||||
//ov::element::i32,
|
||||
ov::element::f32
|
||||
};
|
||||
|
||||
const std::vector<CheckBroadcastTestCaseParams> test_cases = {
|
||||
// broadcast is neccessary
|
||||
{
|
||||
{{1, 3, 4, 4}, {4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::PDPD, -1),
|
||||
1,
|
||||
0
|
||||
},
|
||||
{
|
||||
{{1, 3, 4, 4}, {4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::PDPD, 2),
|
||||
1,
|
||||
0
|
||||
},
|
||||
|
||||
// broadcast is not neccessary
|
||||
{
|
||||
{{1, 3, 4, 4}, {1, 3, 4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::PDPD, -1),
|
||||
1,
|
||||
1
|
||||
},
|
||||
{
|
||||
{{1, 3, 4, 4}, {1, 3, 4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::PDPD, 0),
|
||||
1,
|
||||
1
|
||||
},
|
||||
|
||||
// any other PDPD
|
||||
{
|
||||
{{1, 3, 4, 4}, {4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::NUMPY, -1),
|
||||
1,
|
||||
1
|
||||
},
|
||||
{
|
||||
{{1, 3, 4, 4}, {4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::NUMPY, 0),
|
||||
1,
|
||||
1
|
||||
},
|
||||
{
|
||||
{{1, 3, 4, 4}, {4, 4}},
|
||||
ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::NUMPY, 2),
|
||||
1,
|
||||
1
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_Snippets_CheckBroadcast, CheckBroadcast,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(input_types),
|
||||
::testing::ValuesIn(test_cases),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)),
|
||||
CheckBroadcast::getTestCaseName);
|
||||
|
||||
} // namespace
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "snippets/precision_propagation_convertion.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<std::vector<ov::PartialShape>> input_shapes = {
|
||||
{{ 1, 3, 16, 16 }, { 1, 1, 1, 16 }},
|
||||
};
|
||||
|
||||
const std::vector<std::vector<float>> fake_quantize_intervals = {
|
||||
{0.f, 2.55f, 0.f, 2.55f},
|
||||
{-1.28f, 1.27f, -1.28f, 1.27f}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_Snippets_PrecisionPropagation_Convertion, PrecisionPropagationConvertion,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(input_shapes),
|
||||
::testing::ValuesIn(fake_quantize_intervals),
|
||||
::testing::Values(1),
|
||||
::testing::Values(1),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)),
|
||||
PrecisionPropagationConvertion::getTestCaseName);
|
||||
|
||||
} // namespace
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -155,7 +155,7 @@ protected:
|
||||
};
|
||||
|
||||
TEST_P(MulAddToFMATests, MulAddToFMATests) {
|
||||
auto subgraph = getLoweredSubgraph(snippets_function->getOriginal(), master_shape, cpu_manager, generator);
|
||||
auto subgraph = getLoweredSubgraph(snippets_function->getOriginal(), master_shape, {}, {}, cpu_manager, generator);
|
||||
model = subgraph->body_ptr();
|
||||
model_ref = snippets_function->getLowered();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared_test_classes/base/snippets_test_utils.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
class CheckBroadcastTestCaseParams {
|
||||
public:
|
||||
std::pair<ov::PartialShape, ov::PartialShape> input_shapes;
|
||||
ov::op::AutoBroadcastSpec broadcast;
|
||||
size_t num_nodes;
|
||||
size_t num_subgraphs;
|
||||
};
|
||||
|
||||
typedef std::tuple <
|
||||
ov::element::Type, // input types
|
||||
CheckBroadcastTestCaseParams, // test case details
|
||||
std::string // target device
|
||||
> CheckBroadcastParams;
|
||||
|
||||
class CheckBroadcast : public testing::WithParamInterface<CheckBroadcastParams>,
|
||||
virtual public ov::test::SnippetsTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<CheckBroadcastParams> obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared_test_classes/base/snippets_test_utils.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
typedef std::tuple<
|
||||
std::vector<ov::PartialShape>, // Input shapes
|
||||
std::vector<float>, // FakeQuantize intervals
|
||||
size_t, // Expected num nodes
|
||||
size_t, // Expected num subgraphs
|
||||
std::string // Target Device
|
||||
> PrecisionPropagationParams;
|
||||
|
||||
class PrecisionPropagationConvertion :
|
||||
public testing::WithParamInterface<PrecisionPropagationParams>,
|
||||
virtual public ov::test::SnippetsTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<PrecisionPropagationParams> obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
+1
-1
@@ -20,7 +20,7 @@ std::string FuseFakeQuantizeTransformation::getTestCaseName(const testing::TestP
|
||||
std::tie(targetDevice, testValues) = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
result << targetDevice << "_" <<
|
||||
result << "targetDevice=" << targetDevice << "_" <<
|
||||
testValues.actual.precisionBeforeAdd << "_" <<
|
||||
testValues.actual.add.values.size() << "_" <<
|
||||
testValues.actual.add.outPrecision << "_" <<
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "snippets/check_broadcast.hpp"
|
||||
|
||||
#include "common_test_utils/common_utils.hpp"
|
||||
#include "subgraph_converts.hpp"
|
||||
#include "common_test_utils/ov_tensor_utils.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
class CheckBroadcastFunction {
|
||||
public:
|
||||
static std::shared_ptr<ov::Model> get(
|
||||
const PartialShape& input_shape1,
|
||||
const PartialShape& input_shape2,
|
||||
const ov::element::Type input_type,
|
||||
const ov::op::AutoBroadcastSpec broadcast) {
|
||||
const auto parameter1 = std::make_shared<ngraph::opset1::Parameter>(input_type, input_shape1);
|
||||
parameter1->set_friendly_name("parameter1");
|
||||
|
||||
const auto parameter2 = std::make_shared<ngraph::opset1::Parameter>(input_type, input_shape2);
|
||||
parameter2->set_friendly_name("parameter2");
|
||||
|
||||
std::shared_ptr<Node> parent = std::make_shared<ngraph::opset1::Multiply>(
|
||||
parameter1,
|
||||
parameter2,
|
||||
broadcast);
|
||||
parent->set_friendly_name("multiply");
|
||||
|
||||
const auto result = std::make_shared<ngraph::opset1::Result>(parent);
|
||||
result->set_friendly_name("result");
|
||||
|
||||
return std::make_shared<ngraph::Function>(
|
||||
ngraph::ResultVector{ result },
|
||||
ngraph::ParameterVector{ parameter1, parameter2 },
|
||||
"CheckBroadcastFunction");
|
||||
}
|
||||
};
|
||||
|
||||
std::string CheckBroadcast::getTestCaseName(testing::TestParamInfo<CheckBroadcastParams> obj) {
|
||||
ov::element::Type input_type;
|
||||
CheckBroadcastTestCaseParams test_case_params;
|
||||
std::string target_device;
|
||||
|
||||
std::tie(input_type, test_case_params, target_device) = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
result << "IS=" << test_case_params.input_shapes.first.get_shape() << "_" <<
|
||||
test_case_params.input_shapes.second.get_shape() << "_";
|
||||
result << "IT=" << input_type << "_";
|
||||
result << "BCT=" << test_case_params.broadcast.m_type << "_";
|
||||
result << "BCA=" << test_case_params.broadcast.m_axis << "_";
|
||||
result << "#N=" << test_case_params.num_nodes << "_";
|
||||
result << "#S=" << test_case_params.num_subgraphs << "_";
|
||||
result << "targetDevice=" << target_device;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void CheckBroadcast::SetUp() {
|
||||
ov::element::Type input_type;
|
||||
CheckBroadcastTestCaseParams test_case_params;
|
||||
|
||||
std::tie(input_type, test_case_params, targetDevice) = this->GetParam();
|
||||
ref_num_nodes = test_case_params.num_nodes;
|
||||
ref_num_subgraphs = test_case_params.num_subgraphs;
|
||||
|
||||
init_input_shapes(static_partial_shapes_to_test_representation({
|
||||
test_case_params.input_shapes.first,
|
||||
test_case_params.input_shapes.second}));
|
||||
|
||||
function = CheckBroadcastFunction::get(
|
||||
test_case_params.input_shapes.first,
|
||||
test_case_params.input_shapes.second,
|
||||
input_type,
|
||||
test_case_params.broadcast);
|
||||
}
|
||||
|
||||
TEST_P(CheckBroadcast, CompareWithRefImpl) {
|
||||
run();
|
||||
validateNumSubgraphs();
|
||||
}
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -106,8 +106,8 @@ parameters ConvertInput::generate_params_random() const {
|
||||
break;
|
||||
case ov::element::i32:
|
||||
case ov::element::i8:
|
||||
startFrom = -10;
|
||||
range = 20;
|
||||
startFrom = -32;
|
||||
range = 64;
|
||||
break;
|
||||
case ov::element::u8:
|
||||
startFrom = 10;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "snippets/precision_propagation_convertion.hpp"
|
||||
|
||||
#include "common_test_utils/common_utils.hpp"
|
||||
#include "precision_propagation_convertion_function.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
std::string PrecisionPropagationConvertion::getTestCaseName(testing::TestParamInfo<PrecisionPropagationParams> obj) {
|
||||
std::vector<ov::PartialShape> input_shapes;
|
||||
std::vector<float> fake_quantize_intervals;
|
||||
std::string targetDevice;
|
||||
size_t num_nodes, num_subgraphs;
|
||||
std::tie(input_shapes, fake_quantize_intervals, num_nodes, num_subgraphs, targetDevice) = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
for (size_t i = 0; i < input_shapes.size(); ++i)
|
||||
result << "IS[" << i << "]=" << input_shapes[i] << "_";
|
||||
for (size_t i = 0; i < fake_quantize_intervals.size(); ++i)
|
||||
result << "FQ[" << i << "]=" << fake_quantize_intervals[i] << "_";
|
||||
result << "#N=" << num_nodes << "_";
|
||||
result << "#S=" << num_subgraphs << "_";
|
||||
result << "targetDevice=" << targetDevice;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void PrecisionPropagationConvertion::SetUp() {
|
||||
std::vector<ov::PartialShape> input_shapes;
|
||||
std::vector<float> fake_quantize_intervals;
|
||||
std::tie(input_shapes, fake_quantize_intervals, ref_num_nodes, ref_num_subgraphs, targetDevice) = this->GetParam();
|
||||
init_input_shapes(static_partial_shapes_to_test_representation(input_shapes));
|
||||
|
||||
function = PrecisionPropagationConvertionFunction(input_shapes, ov::element::f32, fake_quantize_intervals).getOriginal();
|
||||
}
|
||||
|
||||
TEST_P(PrecisionPropagationConvertion, CompareWithRefImpl) {
|
||||
run();
|
||||
validateNumSubgraphs();
|
||||
}
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "openvino/core/model.hpp"
|
||||
#include "snippets_helpers.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
/**
|
||||
* @class PrecisionPropagationConvertionFunction
|
||||
* @brief PrecisionPropagationConvertionFunction instance returns reference and original functions.
|
||||
*
|
||||
* Input arguments are used to create function in getOriginal methods only.
|
||||
* Dont use getReference and getLowered method, they are not implemented and throw std::runtime_error exception.
|
||||
* Note, ov::element::Type_t precision base type input argument is not used.
|
||||
*/
|
||||
class PrecisionPropagationConvertionFunction : public SnippetsFunctionBase {
|
||||
public:
|
||||
PrecisionPropagationConvertionFunction(
|
||||
const std::vector<ov::PartialShape>& input_shapes,
|
||||
const element::Type input_type,
|
||||
const std::vector<float>& fake_quantize_intervals);
|
||||
|
||||
/*
|
||||
* Don't call this method explicity. You should create the instance of PrecisionPropagationConvertionFunction before.
|
||||
* After the method will be called implicitly in getOriginal.
|
||||
* Note, please, getReference and getLowered methods are not implemented and throw exception.
|
||||
*/
|
||||
static std::shared_ptr<ov::Model> get(
|
||||
const std::vector<ov::PartialShape>& input_shapes,
|
||||
const element::Type input_type,
|
||||
const std::vector<float>& fake_quantize_intervals);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Model> initOriginal() const override;
|
||||
|
||||
private:
|
||||
const std::vector<float> fake_quantize_intervals;
|
||||
};
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include "ngraph/opsets/opset1.hpp"
|
||||
#include "snippets/op/convert_saturation.hpp"
|
||||
#include "snippets_helpers.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
/**
|
||||
* @class DummyAdd
|
||||
* @brief DummyAdd operation has custom validate_and_infer_types method implementation.
|
||||
*/
|
||||
class DummyAdd : public ngraph::opset1::Add {
|
||||
public:
|
||||
OPENVINO_OP("DummyAdd", "test::snippets");
|
||||
|
||||
DummyAdd(const Output<Node>& arg0,
|
||||
const Output<Node>& arg1,
|
||||
const ngraph::op::AutoBroadcastSpec& auto_broadcast =
|
||||
ngraph::op::AutoBroadcastSpec(ngraph::op::AutoBroadcastType::NUMPY))
|
||||
: ngraph::opset1::Add(arg0, arg1, auto_broadcast) {
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
DummyAdd(const ngraph::opset1::Add& add)
|
||||
: Add(add.get_input_source_output(0), add.get_input_source_output(1), add.get_autob()) {
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
DummyAdd() = default;
|
||||
|
||||
void validate_and_infer_types() override {
|
||||
const auto input_type1 = get_input_element_type(0);
|
||||
const auto input_type2 = get_input_element_type(1);
|
||||
|
||||
const element::Type output_type = (input_type1 == element::i8) || (input_type2 == element::i8) ?
|
||||
element::i32 :
|
||||
get_input_element_type(0);
|
||||
|
||||
set_output_type(0, output_type, get_input_partial_shape(0));
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override {
|
||||
return std::make_shared<DummyAdd>(new_args.at(0), new_args.at(1), this->get_autob());
|
||||
}
|
||||
};
|
||||
|
||||
class PrecisionPropagationAddFunctionParams {
|
||||
public:
|
||||
class Actual {
|
||||
public:
|
||||
std::pair<element::Type, element::Type> convertion_before_op1;
|
||||
element::Type convertion_before_op2_1;
|
||||
std::pair<element::Type, element::Type> convertion_before_op2_2;
|
||||
};
|
||||
|
||||
class Expected {
|
||||
public:
|
||||
std::pair<element::Type, element::Type> convertion_before_op1;
|
||||
element::Type convertion_before_op2_1;
|
||||
std::pair<element::Type, element::Type> convertion_before_op2_2;
|
||||
element::Type convertion_after_op2;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PrecisionPropagationAddFunction
|
||||
* @brief PrecisionPropagationAddFunction instance returns reference and original functions.
|
||||
*
|
||||
* Input arguments are used to create function in getOriginal or getReference methods only.
|
||||
* Dont use getLowered method, it is not implemented and throw std::runtime_error exception.
|
||||
* Note, ov::element::Type_t precision base type input argument is not used.
|
||||
*/
|
||||
class PrecisionPropagationAddFunction : public SnippetsFunctionBase {
|
||||
public:
|
||||
explicit PrecisionPropagationAddFunction(
|
||||
const std::vector<PartialShape> input_shapes,
|
||||
const ngraph::element::Type precision1,
|
||||
const ngraph::element::Type precision2,
|
||||
const ngraph::element::Type constant_precision,
|
||||
PrecisionPropagationAddFunctionParams::Actual actual,
|
||||
PrecisionPropagationAddFunctionParams::Expected expected) :
|
||||
SnippetsFunctionBase(input_shapes),
|
||||
precision1(precision1),
|
||||
precision2(precision2),
|
||||
constant_precision(constant_precision),
|
||||
actual(actual),
|
||||
expected(expected) {
|
||||
OPENVINO_ASSERT(input_shapes.size() == 2ull, "input_shapes size has to be equal to 2");
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't call this method explicity. You should create the instance of PrecisionPropagationAddFunction before.
|
||||
* After the method will be called implicitly in getOriginal or getReference methods.
|
||||
* Note, please, getLowered method is not implemented and throws exception.
|
||||
*/
|
||||
static std::shared_ptr<ngraph::Function> get(
|
||||
const ngraph::element::Type precision1,
|
||||
const ngraph::PartialShape& inputShape1,
|
||||
const ngraph::element::Type precision2,
|
||||
const ngraph::PartialShape& inputShape2,
|
||||
const ngraph::element::Type constant_precision,
|
||||
const std::pair<element::Type, element::Type>& convertion_before_op1 = std::pair<element::Type, element::Type>(),
|
||||
const element::Type convertion_before_op2_1 = element::undefined,
|
||||
const std::pair<element::Type, element::Type>& convertion_before_op2_2 = std::pair<element::Type, element::Type>(),
|
||||
const element::Type convertion_after_op2 = {});
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ov::Model> initOriginal() const override;
|
||||
std::shared_ptr<ov::Model> initReference() const override;
|
||||
|
||||
const ngraph::element::Type precision1;
|
||||
const ngraph::element::Type precision2;
|
||||
const ngraph::element::Type constant_precision;
|
||||
const PrecisionPropagationAddFunctionParams::Actual actual;
|
||||
const PrecisionPropagationAddFunctionParams::Expected expected;
|
||||
};
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
@@ -17,6 +17,7 @@ using ov::Model;
|
||||
class SnippetsFunctionBase {
|
||||
public:
|
||||
SnippetsFunctionBase() = delete;
|
||||
virtual ~SnippetsFunctionBase() = default;
|
||||
|
||||
explicit SnippetsFunctionBase(const std::vector<PartialShape>& inputShapes, ov::element::Type_t precision = element::f32)
|
||||
: precision{precision}, input_shapes{inputShapes} {}
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "precision_propagation_convertion_function.hpp"
|
||||
#include <assert.h>
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
namespace {
|
||||
std::shared_ptr<ngraph::op::FakeQuantize> make_fake_quantize(
|
||||
const Output<Node>& parent,
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const element::Type inputType,
|
||||
const std::vector<float>& fake_quantize_intervals) {
|
||||
auto generate = [](const ov::element::Type precision,
|
||||
const ngraph::Shape& shape,
|
||||
const float initialValue,
|
||||
const std::string& name) {
|
||||
const auto size = ngraph::shape_size(shape);
|
||||
std::vector<float> values(size);
|
||||
for (auto i = 0; i < size; ++i) {
|
||||
values[i] = static_cast<float>(initialValue + i);
|
||||
}
|
||||
auto constant = std::make_shared<ngraph::opset1::Constant>(precision, shape, values);
|
||||
constant->set_friendly_name(name);
|
||||
return constant;
|
||||
};
|
||||
|
||||
const auto fakeQuantize = std::make_shared<ngraph::opset1::FakeQuantize>(
|
||||
parent,
|
||||
generate(inputType, {}, fake_quantize_intervals[0], "inputLow"),
|
||||
generate(inputType, {}, fake_quantize_intervals[1], "inputHigh"),
|
||||
generate(inputType, {}, fake_quantize_intervals[2], "outputLow"),
|
||||
generate(inputType, {}, fake_quantize_intervals[3], "outputHigh"),
|
||||
256ul);
|
||||
fakeQuantize->set_friendly_name("fakeQuantize");
|
||||
|
||||
return fakeQuantize;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
PrecisionPropagationConvertionFunction::PrecisionPropagationConvertionFunction(
|
||||
const std::vector<ov::PartialShape>& input_shapes,
|
||||
const element::Type input_type,
|
||||
const std::vector<float>& fake_quantize_intervals) :
|
||||
SnippetsFunctionBase(input_shapes, input_type),
|
||||
fake_quantize_intervals(fake_quantize_intervals) {
|
||||
}
|
||||
|
||||
std::shared_ptr<ov::Model> PrecisionPropagationConvertionFunction::get(
|
||||
const std::vector<ov::PartialShape>& input_shapes,
|
||||
const element::Type input_type,
|
||||
const std::vector<float>& fake_quantize_intervals) {
|
||||
assert(2ull == input_shapes.size());
|
||||
assert(4ull == fake_quantize_intervals.size());
|
||||
const auto parameter1 = std::make_shared<ngraph::opset1::Parameter>(input_type, input_shapes[0]);
|
||||
parameter1->set_friendly_name("parameter1");
|
||||
|
||||
const auto parameter2 = std::make_shared<ngraph::opset1::Parameter>(input_type, input_shapes[1]);
|
||||
parameter2->set_friendly_name("parameter2");
|
||||
|
||||
std::shared_ptr<Node> parent = make_fake_quantize(
|
||||
parameter1,
|
||||
input_shapes[0],
|
||||
input_type,
|
||||
fake_quantize_intervals);
|
||||
parent->set_friendly_name("fakeQuantize");
|
||||
|
||||
parent = std::make_shared<ngraph::opset1::Add>(parent, parameter2);
|
||||
parent->set_friendly_name("add");
|
||||
|
||||
const auto result = std::make_shared<ngraph::opset1::Result>(parent);
|
||||
result->set_friendly_name("result");
|
||||
|
||||
auto function = std::make_shared<ngraph::Function>(
|
||||
ngraph::ResultVector{ result },
|
||||
ParameterVector{ parameter1, parameter2 },
|
||||
"PrecisionPropagationConvertionFunction");
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> PrecisionPropagationConvertionFunction::initOriginal() const {
|
||||
return get(input_shapes, precision, fake_quantize_intervals);
|
||||
}
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "precision_propagation_function.hpp"
|
||||
#include <assert.h>
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
|
||||
namespace ov {
|
||||
namespace test {
|
||||
namespace snippets {
|
||||
|
||||
std::shared_ptr<ngraph::Function> PrecisionPropagationAddFunction::get(
|
||||
const ngraph::element::Type precision1,
|
||||
const ngraph::PartialShape& inputShape1,
|
||||
const ngraph::element::Type precision2,
|
||||
const ngraph::PartialShape& inputShape2,
|
||||
const ngraph::element::Type constant_precision,
|
||||
const std::pair<element::Type, element::Type>& convertion_before_op1,
|
||||
const element::Type convertion_before_op2_1,
|
||||
const std::pair<element::Type, element::Type>& convertion_before_op2_2,
|
||||
const element::Type convertion_after_op2) {
|
||||
const auto create_convert = [](std::shared_ptr<Node> parent, const element::Type convertion_type) -> std::shared_ptr<Node> {
|
||||
return convertion_type == element::undefined
|
||||
? std::dynamic_pointer_cast<Node>(parent)
|
||||
: std::make_shared<ngraph::snippets::op::ConvertSaturation>(parent, convertion_type);
|
||||
};
|
||||
|
||||
const auto make_branch = [&create_convert](
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const size_t index,
|
||||
const element::Type convertion_type) -> std::pair<std::shared_ptr<ngraph::opset1::Parameter>, std::shared_ptr<ov::Node>> {
|
||||
const auto parameter = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
|
||||
parameter->set_friendly_name("parameter" + std::to_string(index));
|
||||
|
||||
std::shared_ptr<Node> parent = create_convert(parameter, convertion_type);
|
||||
|
||||
return { parameter, parent };
|
||||
};
|
||||
|
||||
const auto branch1 = make_branch(precision1, inputShape1, 1, convertion_before_op1.first);
|
||||
const auto branch2 = make_branch(precision2, inputShape2, 2, convertion_before_op1.second);
|
||||
|
||||
std::shared_ptr<Node> parent = std::make_shared<DummyAdd>(branch1.second, branch2.second);
|
||||
parent->set_friendly_name("add");
|
||||
|
||||
parent = create_convert(parent, convertion_before_op2_1);
|
||||
|
||||
const auto maximum_in2_type = convertion_before_op2_2.second == element::undefined ?
|
||||
constant_precision :
|
||||
convertion_before_op2_2.second;
|
||||
if ((convertion_before_op2_2.first == element::undefined) &&
|
||||
(parent->get_output_element_type(0) != maximum_in2_type)) {
|
||||
parent = std::make_shared<ngraph::snippets::op::ConvertSaturation>(parent, maximum_in2_type);
|
||||
}
|
||||
|
||||
parent = std::make_shared<ngraph::opset1::Maximum>(
|
||||
create_convert(parent, convertion_before_op2_2.first),
|
||||
create_convert(
|
||||
std::make_shared<ngraph::opset1::Constant>(constant_precision, Shape{}, std::vector<float>{0.f}),
|
||||
convertion_before_op2_2.second));
|
||||
parent->set_friendly_name("maximum");
|
||||
|
||||
parent = create_convert(parent, convertion_after_op2);
|
||||
|
||||
const auto result = std::make_shared<ngraph::opset1::Result>(parent);
|
||||
auto& result_out_tensor = result->get_output_tensor(0);
|
||||
result_out_tensor.set_names({ "result_tensor" });
|
||||
result->set_friendly_name("result");
|
||||
|
||||
const ngraph::ResultVector results{ result };
|
||||
const ngraph::ParameterVector parameters{ branch1.first, branch2.first };
|
||||
const auto model = std::make_shared<ngraph::Function>(results, parameters, "SnippetsPrecisionPropagation");
|
||||
return model;
|
||||
}
|
||||
|
||||
std::shared_ptr<ov::Model> PrecisionPropagationAddFunction::initOriginal() const {
|
||||
return get(
|
||||
precision1,
|
||||
input_shapes[0],
|
||||
precision2,
|
||||
input_shapes[1],
|
||||
constant_precision,
|
||||
actual.convertion_before_op1,
|
||||
actual.convertion_before_op2_1,
|
||||
actual.convertion_before_op2_2);
|
||||
}
|
||||
|
||||
std::shared_ptr<ov::Model> PrecisionPropagationAddFunction::initReference() const {
|
||||
return get(
|
||||
precision1,
|
||||
input_shapes[0],
|
||||
precision2,
|
||||
input_shapes[1],
|
||||
constant_precision,
|
||||
expected.convertion_before_op1,
|
||||
expected.convertion_before_op2_1,
|
||||
expected.convertion_before_op2_2,
|
||||
expected.convertion_after_op2);
|
||||
}
|
||||
|
||||
} // namespace snippets
|
||||
} // namespace test
|
||||
} // namespace ov
|
||||
Reference in new issue
Block a user