This reverts commit c5824b8494
.
This commit is contained in:
parent
7d198a8535
commit
d51f337934
@ -5,7 +5,6 @@
|
||||
#include "int_executable.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <openvino/op/util/variable_context.hpp>
|
||||
|
||||
#include "evaluates_map.hpp"
|
||||
#include "ngraph/except.hpp"
|
||||
@ -88,10 +87,6 @@ bool runtime::interpreter::INTExecutable::call(const vector<shared_ptr<runtime::
|
||||
results_map[output] = output_count;
|
||||
}
|
||||
|
||||
EvaluationContext eval_context;
|
||||
ov::op::util::VariableContext variable_context;
|
||||
eval_context.emplace("VariableContext", variable_context);
|
||||
|
||||
// for each ordered op in the graph
|
||||
for (const auto& op : m_nodes) {
|
||||
if (dynamic_pointer_cast<op::Parameter>(op) != nullptr) {
|
||||
@ -148,20 +143,8 @@ bool runtime::interpreter::INTExecutable::call(const vector<shared_ptr<runtime::
|
||||
if (m_performance_counters_enabled) {
|
||||
m_timer_map[op].start();
|
||||
}
|
||||
|
||||
if (auto var_extension = std::dynamic_pointer_cast<ov::op::util::VariableExtension>(cloned_node)) {
|
||||
auto variable = var_extension->get_variable();
|
||||
if (!variable_context.get_variable_value(variable)) {
|
||||
auto h_tensor = std::make_shared<ngraph::HostTensor>(cloned_node->get_input_element_type(0),
|
||||
cloned_node->get_input_shape(0));
|
||||
std::vector<float> data(ov::shape_size(cloned_node->get_input_shape(0)), 0);
|
||||
h_tensor->write(data.data(), data.size() * sizeof(float));
|
||||
variable_context.set_variable_value(variable, std::make_shared<VariableValue>(h_tensor));
|
||||
}
|
||||
}
|
||||
|
||||
// Call evaluate for cloned_node with static shapes
|
||||
if (!cloned_node->evaluate(op_outputs, op_inputs, eval_context)) {
|
||||
if (!cloned_node->evaluate(op_outputs, op_inputs)) {
|
||||
evaluate_node(cloned_node, op_outputs, op_inputs);
|
||||
}
|
||||
if (m_performance_counters_enabled) {
|
||||
|
@ -85,7 +85,6 @@ NGRAPH_OP(NonMaxSuppression, op::v5)
|
||||
NGRAPH_OP(RNNSequence, op::v5)
|
||||
NGRAPH_OP(Round, op::v5)
|
||||
|
||||
NGRAPH_OP(Assign, ngraph::op::v6)
|
||||
NGRAPH_OP(CTCGreedyDecoderSeqLen, op::v6)
|
||||
NGRAPH_OP(ExperimentalDetectronDetectionOutput, op::v6)
|
||||
NGRAPH_OP(ExperimentalDetectronGenerateProposalsSingleImage, op::v6)
|
||||
@ -94,7 +93,6 @@ NGRAPH_OP(ExperimentalDetectronROIFeatureExtractor, op::v6)
|
||||
NGRAPH_OP(ExperimentalDetectronTopKROIs, op::v6)
|
||||
NGRAPH_OP(GatherElements, op::v6)
|
||||
NGRAPH_OP(MVN, ngraph::op::v6)
|
||||
NGRAPH_OP(ReadValue, ngraph::op::v6)
|
||||
|
||||
NGRAPH_OP(DFT, op::v7)
|
||||
NGRAPH_OP(Einsum, op::v7)
|
||||
|
@ -1,27 +0,0 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include "layer_transformation.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
namespace low_precision {
|
||||
|
||||
class LP_TRANSFORMATIONS_API AssignAndReadValueTransformation : public LayerTransformation {
|
||||
public:
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
AssignAndReadValueTransformation(const std::shared_ptr<ngraph::Function> function, const Params& params = Params());
|
||||
bool transform(TransformationContext& context, ngraph::pattern::Matcher& m) override;
|
||||
bool canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> op) const override;
|
||||
bool isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept override;
|
||||
private:
|
||||
std::shared_ptr<ngraph::Function> function;
|
||||
};
|
||||
|
||||
} // namespace low_precision
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
@ -33,7 +33,6 @@ public:
|
||||
bool multiplyHasZeroOrDenormal() const;
|
||||
bool isShared() const;
|
||||
bool isLowPrecision() const;
|
||||
std::shared_ptr<Node> copyWithNewInput(const std::shared_ptr<Node>& input) const;
|
||||
|
||||
static bool checkElementwise(const std::shared_ptr<ngraph::Node>& elementwise);
|
||||
|
||||
|
@ -22,10 +22,11 @@ public:
|
||||
|
||||
static bool checkElementwise(const std::shared_ptr<Node>& eltwise);
|
||||
|
||||
static std::shared_ptr<opset1::FakeQuantize> fuseElementwise(
|
||||
private:
|
||||
std::shared_ptr<opset1::FakeQuantize> fuseElementwise(
|
||||
TransformationContext& context,
|
||||
MatcherPass* matcherPass,
|
||||
const std::shared_ptr<opset1::FakeQuantize>& fakeQuantize);
|
||||
const std::shared_ptr<opset1::FakeQuantize>& fakeQuantize) const;
|
||||
};
|
||||
|
||||
} // namespace low_precision
|
||||
|
@ -41,12 +41,17 @@ public:
|
||||
|
||||
static std::vector<Input<Node>> consumer_inputs(std::shared_ptr<Node> node);
|
||||
|
||||
// returns true if at least one child is not FQ
|
||||
static bool notAllChildrensAreFQ(const NodeVector& layer);
|
||||
|
||||
// Collect and return a vector with all nodes that consumes any of the `node` output
|
||||
static std::vector<std::shared_ptr<Node>> consumers(std::shared_ptr<Node> node);
|
||||
|
||||
// return true if op is on a constant path
|
||||
static bool isConstantPath(const std::shared_ptr<Node>& op);
|
||||
|
||||
static Shape alignShapeForChannelDim(const Shape& shape, Rank rank);
|
||||
|
||||
template <typename OperationType>
|
||||
static std::shared_ptr<Node> setOutDataPrecisionForTypeRelaxed(std::shared_ptr<OperationType> operation, const element::Type& precision);
|
||||
|
||||
@ -210,6 +215,87 @@ public:
|
||||
const std::shared_ptr<Node>& dequantization,
|
||||
const std::shared_ptr<Node>& newNode);
|
||||
|
||||
static void replaceAttributeInNodes(
|
||||
std::shared_ptr<ngraph::Function> f,
|
||||
const std::string& name,
|
||||
const ov::Any& newAttribute,
|
||||
const ov::Any& oldAttribute,
|
||||
const std::shared_ptr<ngraph::Node>& initialNode) {
|
||||
std::set<std::shared_ptr<Node>> visited;
|
||||
std::deque<std::shared_ptr<Node>> nodes;
|
||||
nodes.emplace_back(initialNode);
|
||||
|
||||
while (!nodes.empty()) {
|
||||
auto node = nodes.front();
|
||||
nodes.pop_front();
|
||||
|
||||
if (visited.count(node) || ov::is_type<op::Constant>(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
visited.insert(node);
|
||||
|
||||
bool handleConnectedNodes = false;
|
||||
if (NetworkHelper::isPrecisionPreserved(node) || ov::is_type<opset1::FakeQuantize>(node)) {
|
||||
auto& rt = node->get_rt_info();
|
||||
|
||||
if (node == initialNode) {
|
||||
rt[name] = newAttribute;
|
||||
handleConnectedNodes = true;
|
||||
} else {
|
||||
auto it = rt.find(name);
|
||||
if (it != rt.end()) {
|
||||
const auto currentAttribute = it->second;
|
||||
if (oldAttribute == currentAttribute) {
|
||||
rt[name] = newAttribute;
|
||||
}
|
||||
handleConnectedNodes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handleConnectedNodes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ov::is_type<opset1::FakeQuantize>(node)) {
|
||||
for (size_t index = 0ul; index < node->get_input_size(); ++index) {
|
||||
auto getInput = [](const std::shared_ptr<ngraph::Node>& node, const size_t index) {
|
||||
const auto dequantization = NetworkHelper::getDequantization(node, index);
|
||||
if (!dequantization.empty() &&
|
||||
(ov::is_type<opset1::Convert>(dequantization.data.get_node())) &&
|
||||
ov::is_type<opset1::FakeQuantize>(dequantization.data.get_node()->get_input_node_ptr(0))) {
|
||||
const auto input = dequantization.data.get_node()->input(0);
|
||||
return input;
|
||||
}
|
||||
return node->input(index);
|
||||
};
|
||||
|
||||
const auto& input = getInput(node, index);
|
||||
const auto& input_node = input.get_source_output().get_node_shared_ptr();
|
||||
|
||||
//const auto& input_node = input.get_source_output().get_node_shared_ptr();
|
||||
if (visited.count(input_node) || ov::is_type<op::Constant>(input_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodes.push_front(input_node);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& output : node->outputs()) {
|
||||
for (auto& input_value : output.get_target_inputs()) {
|
||||
const auto& output_node = input_value.get_node()->shared_from_this();
|
||||
if (visited.count(output_node) || ov::is_type<op::Constant>(output_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodes.push_front(output_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SharedAttribute>
|
||||
static void reassign(
|
||||
const std::shared_ptr<typename SharedAttribute::SharedValueAttribute::SharedValue>& sharedValue,
|
||||
@ -284,6 +370,14 @@ std::shared_ptr<Node> make_op_pattern(const ngraph::NodeVector& args) {
|
||||
return std::make_shared<ngraph::pattern::op::Any>(element::undefined, PartialShape{}, [](std::shared_ptr<Node> n) {return !!ov::as_type_ptr<T>(n); }, args);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<Node> make_op_label() {
|
||||
return std::make_shared<ngraph::pattern::op::Label>(
|
||||
element::undefined,
|
||||
PartialShape{},
|
||||
[](std::shared_ptr<Node> n) {return !!ov::as_type_ptr<T>(n); });
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
std::shared_ptr<Node> fold(Args&&... args) {
|
||||
auto node = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
@ -1,132 +0,0 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "low_precision/assign_and_read_value.hpp"
|
||||
#include <ngraph/ngraph.hpp>
|
||||
|
||||
#include <ngraph/pattern/op/wrap_type.hpp>
|
||||
#include "low_precision/network_helper.hpp"
|
||||
#include <ngraph/opsets/opset6.hpp>
|
||||
#include <ngraph/pattern/op/or.hpp>
|
||||
#include <openvino/op/util/assign_base.hpp>
|
||||
#include "low_precision/fake_quantize.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
namespace low_precision {
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(ngraph::pass::low_precision::AssignAndReadValueTransformation, "AssignAndReadValueTransformation", 0);
|
||||
|
||||
AssignAndReadValueTransformation::AssignAndReadValueTransformation(const std::shared_ptr<ngraph::Function> function, const Params& params) :
|
||||
LayerTransformation(params), function(function) {
|
||||
auto assign3 = pattern::wrap_type<opset3::Assign>({ pattern::wrap_type<opset1::Multiply>() });
|
||||
auto assign6 = pattern::wrap_type<opset6::Assign>({ pattern::wrap_type<opset1::Multiply>() });
|
||||
|
||||
ngraph::graph_rewrite_callback callback = [=](pattern::Matcher& m) {
|
||||
const auto& opsMap = m.get_pattern_value_map();
|
||||
auto op = m.get_match_root();
|
||||
auto assignIt = opsMap.find(assign3);
|
||||
if (assignIt == opsMap.end()) {
|
||||
assignIt = opsMap.find(assign6);
|
||||
}
|
||||
const auto assign = assignIt->second.get_node_shared_ptr();
|
||||
// check that we have ReadValue as the first dependency
|
||||
if (assign->get_control_dependencies().empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transformation_callback(op)) {
|
||||
return false;
|
||||
}
|
||||
return transform(*context, m);
|
||||
};
|
||||
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(
|
||||
std::make_shared<pattern::op::Or>(OutputVector{ assign3, assign6 }),
|
||||
"AssignAndReadValueTransformation");
|
||||
this->register_matcher(m, callback);
|
||||
}
|
||||
|
||||
bool AssignAndReadValueTransformation::transform(TransformationContext& context, ngraph::pattern::Matcher& m) {
|
||||
if (!canBeTransformed(context, m.get_match_root())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto oldAssign = m.get_match_root();
|
||||
const auto readValue = oldAssign->get_control_dependencies()[0];
|
||||
oldAssign->remove_control_dependency(readValue);
|
||||
|
||||
const auto assign = NetworkHelper::separateInStandaloneBranch(oldAssign);
|
||||
const auto dequantization = NetworkHelper::getDequantization(assign);
|
||||
|
||||
auto oldVar = ov::as_type_ptr<op::ReadValueBase>(readValue)->get_variable();
|
||||
auto variableInfo = oldVar->get_info();
|
||||
// set new precision for oldVar to update precision in newReadValue
|
||||
oldVar->update({variableInfo.data_shape, dequantization.data.get_element_type(), variableInfo.variable_id});
|
||||
// transform ReadValue part
|
||||
const auto newConstant = foldConvert(readValue->get_input_node_shared_ptr(0), dequantization.data.get_element_type());
|
||||
const auto newReadValue = readValue->copy_with_new_inputs({newConstant});
|
||||
const auto newDequantization = dequantization.copyWithNewInput(newReadValue);
|
||||
replace_node(readValue, newDequantization);
|
||||
|
||||
// transform Assign part
|
||||
|
||||
const auto newAssign = assign->copy_with_new_inputs({dequantization.data});
|
||||
function->remove_sink(as_type_ptr<op::Sink>(oldAssign));
|
||||
function->add_sinks({as_type_ptr<op::Sink>(newAssign)});
|
||||
|
||||
NetworkHelper::copyInfo(assign, newAssign);
|
||||
replace_node(assign, newAssign);
|
||||
newAssign->add_control_dependency(newReadValue);
|
||||
|
||||
// fuse dequantization multiply with FQ after ReadValue if possible
|
||||
const auto nextLayers = newDequantization->get_output_target_inputs(0);
|
||||
if (nextLayers.size() > 1) {
|
||||
return true;
|
||||
}
|
||||
const auto fakeQuantize = as_type_ptr<opset1::FakeQuantize>(nextLayers.begin()->get_node()->shared_from_this());
|
||||
|
||||
if (fakeQuantize == nullptr) {
|
||||
return true;
|
||||
}
|
||||
auto fakeQuantizeInputs = fakeQuantize->input_values();
|
||||
|
||||
const auto inputLow = as_type_ptr<opset1::Constant>(fakeQuantizeInputs[1].get_node_shared_ptr());
|
||||
const auto inputHigh = as_type_ptr<opset1::Constant>(fakeQuantizeInputs[2].get_node_shared_ptr());
|
||||
|
||||
if (inputLow == nullptr || inputHigh == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FakeQuantizeTransformation::fuseElementwise(context, this, fakeQuantize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssignAndReadValueTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> op) const {
|
||||
if (!LayerTransformation::canBeTransformed(context, op)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto readValue = std::dynamic_pointer_cast<op::ReadValueBase>(op->get_control_dependencies()[0]);
|
||||
if (!readValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: remove this limitation and change the transformation when this constant will be accepted to be non-zero
|
||||
if (!NetworkHelper::isZeroConst(readValue->get_input_node_shared_ptr(0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto dequantization = NetworkHelper::getDequantization(op);
|
||||
return dequantization.subtract == nullptr && dequantization.multiply != nullptr;
|
||||
}
|
||||
|
||||
bool AssignAndReadValueTransformation::isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace low_precision
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
@ -129,15 +129,17 @@ bool FakeQuantizeTransformation::checkElementwise(const std::shared_ptr<Node>& e
|
||||
std::shared_ptr<opset1::FakeQuantize> FakeQuantizeTransformation::fuseElementwise(
|
||||
TransformationContext& context,
|
||||
MatcherPass* matcherPass,
|
||||
const std::shared_ptr<opset1::FakeQuantize>& fakeQuantize) {
|
||||
const std::shared_ptr<opset1::FakeQuantize>& fakeQuantize) const {
|
||||
const std::shared_ptr<Node> eltwise = fakeQuantize->get_input_node_shared_ptr(0);
|
||||
|
||||
std::shared_ptr<Node> inputLowConst_f32 = foldConvert(fakeQuantize->input_value(1), element::f32);
|
||||
std::shared_ptr<Node> inputHighConst_f32 = foldConvert(fakeQuantize->input_value(2), element::f32);
|
||||
std::shared_ptr<Node> inputLowConst_f32 = foldConvert(fakeQuantize->input_value(1), deqPrecision);
|
||||
std::shared_ptr<Node> inputHighConst_f32 = foldConvert(fakeQuantize->input_value(2), deqPrecision);
|
||||
|
||||
std::shared_ptr<opset1::Constant> constant = fq::getConstant(eltwise);
|
||||
if (ov::is_type<opset1::Multiply>(eltwise) && checkElementwise(eltwise)) {
|
||||
const auto value = foldConvert(constant, element::f32);
|
||||
const auto value = constant->get_output_element_type(0) == deqPrecision ?
|
||||
constant :
|
||||
foldConvert(constant, deqPrecision);
|
||||
|
||||
const auto valueVec = ov::as_type_ptr<opset1::Constant>(value)->cast_vector<float>();
|
||||
|
||||
@ -157,7 +159,9 @@ std::shared_ptr<opset1::FakeQuantize> FakeQuantizeTransformation::fuseElementwis
|
||||
inputLowConst_f32 = fq::updateShape(inputLowConst_f32, fakeQuantize->get_output_partial_shape(0));
|
||||
inputHighConst_f32 = fq::updateShape(inputHighConst_f32, fakeQuantize->get_output_partial_shape(0));
|
||||
} else if (ov::is_type<opset1::Subtract>(eltwise) && checkElementwise(eltwise)) {
|
||||
const auto value = foldConvert(constant, element::f32);
|
||||
const auto value = constant->get_output_element_type(0) == deqPrecision ?
|
||||
constant :
|
||||
foldConvert(constant, deqPrecision);
|
||||
|
||||
inputLowConst_f32 = fq::updateShape(fold<opset1::Add>(inputLowConst_f32, value), fakeQuantize->get_output_partial_shape(0));
|
||||
inputHighConst_f32 = fq::updateShape(fold<opset1::Add>(inputHighConst_f32, value), fakeQuantize->get_output_partial_shape(0));
|
||||
@ -169,7 +173,9 @@ std::shared_ptr<opset1::FakeQuantize> FakeQuantizeTransformation::fuseElementwis
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto value = foldConvert(constant, element::f32);
|
||||
const auto value = constant->get_output_element_type(0) == deqPrecision ?
|
||||
constant :
|
||||
foldConvert(constant, deqPrecision);
|
||||
|
||||
inputLowConst_f32 = fq::updateShape(fold<opset1::Subtract>(inputLowConst_f32, value), fakeQuantize->get_output_partial_shape(0));
|
||||
inputHighConst_f32 = fq::updateShape(fold<opset1::Subtract>(inputHighConst_f32, value), fakeQuantize->get_output_partial_shape(0));
|
||||
@ -190,8 +196,8 @@ std::shared_ptr<opset1::FakeQuantize> FakeQuantizeTransformation::fuseElementwis
|
||||
data->output(outputIdx),
|
||||
inputLowConst_f32,
|
||||
inputHighConst_f32,
|
||||
foldConvert(fakeQuantize->input_value(3), element::f32),
|
||||
foldConvert(fakeQuantize->input_value(4), element::f32) }));
|
||||
foldConvert(fakeQuantize->input_value(3), deqPrecision),
|
||||
foldConvert(fakeQuantize->input_value(4), deqPrecision) }));
|
||||
|
||||
matcherPass->register_new_node(newFakeQuantize);
|
||||
|
||||
|
@ -155,26 +155,6 @@ bool FakeQuantizeDequantization::checkElementwise(const std::shared_ptr<ngraph::
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> FakeQuantizeDequantization::copyWithNewInput(const std::shared_ptr<Node>& input) const {
|
||||
auto lastNode = input;
|
||||
if (convert) {
|
||||
lastNode = convert->copy_with_new_inputs({lastNode});
|
||||
}
|
||||
if (subtract) {
|
||||
std::shared_ptr<Node> input1 = nullptr;
|
||||
if (subtractConvert) {
|
||||
input1 = subtractConvert;
|
||||
} else {
|
||||
input1 = subtractConstant;
|
||||
}
|
||||
lastNode = subtract->copy_with_new_inputs({lastNode, input1});
|
||||
}
|
||||
if (multiply) {
|
||||
lastNode = multiply->copy_with_new_inputs({lastNode, multiplyConstant});
|
||||
}
|
||||
return lastNode;
|
||||
}
|
||||
|
||||
int FakeQuantizeDequantization::fillDequantizationParams(
|
||||
const std::shared_ptr<ngraph::Node>& elementwise,
|
||||
std::shared_ptr<ngraph::opset1::Convert>& convert,
|
||||
|
@ -38,7 +38,6 @@
|
||||
|
||||
// general transformations
|
||||
#include "low_precision/add.hpp"
|
||||
#include "low_precision/assign_and_read_value.hpp"
|
||||
#include "low_precision/avg_pool.hpp"
|
||||
#include "low_precision/clamp.hpp"
|
||||
#include "low_precision/convolution.hpp"
|
||||
@ -208,7 +207,6 @@ bool ngraph::pass::low_precision::LowPrecision::run_on_model(const std::shared_p
|
||||
|
||||
std::shared_ptr<ngraph::pass::GraphRewrite> common = manager.register_pass<ngraph::pass::GraphRewrite>();
|
||||
common->add_matcher<ngraph::pass::low_precision::AddTransformation>(params);
|
||||
common->add_matcher<ngraph::pass::low_precision::AssignAndReadValueTransformation>(f, params);
|
||||
common->add_matcher<ngraph::pass::low_precision::AvgPoolTransformation>(params);
|
||||
common->add_matcher<ngraph::pass::low_precision::ClampTransformation>(params);
|
||||
common->add_matcher<ngraph::pass::low_precision::ConcatTransformation>(params);
|
||||
|
@ -37,6 +37,17 @@ bool NetworkHelper::is_castable_to_one_of(NodeTypeInfo type, const std::unordere
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkHelper::notAllChildrensAreFQ(const NodeVector& childrens) {
|
||||
// NOTE: This check was added for models that don't have FQ after AvgPool
|
||||
// They will have transparent precision as it was in old LPT.
|
||||
for (const auto& child : childrens) {
|
||||
if (!ov::is_type<opset1::FakeQuantize>(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Collect and return a vector with all nodes that consumes any of the `node` output
|
||||
std::vector<Input<Node>> NetworkHelper::consumer_inputs(std::shared_ptr<Node> node) {
|
||||
std::vector<Input<Node>> result;
|
||||
@ -188,6 +199,15 @@ size_t NetworkHelper::getGroupsCount(std::shared_ptr<Node> layer) {
|
||||
}
|
||||
}
|
||||
|
||||
// Assumin tensor in NC... layout, append necessary number of 1s to shape to align it to a give rank
|
||||
Shape NetworkHelper::alignShapeForChannelDim(const Shape& shape, Rank rank) {
|
||||
assert(shape.size() == 1);
|
||||
assert(rank.is_static());
|
||||
Shape result = shape;
|
||||
result.resize(rank.get_length() - 1, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
void NetworkHelper::removeLayer(std::shared_ptr<Node> layer) {
|
||||
ngraph::replace_output_update_name(layer->output(0), layer->input_value(0));
|
||||
}
|
||||
@ -1339,12 +1359,9 @@ FakeQuantizeDequantization NetworkHelper::getDequantization(const std::shared_pt
|
||||
|
||||
const std::shared_ptr<opset1::Convert> convert = ov::as_type_ptr<opset1::Convert>(dataNode.get_node_shared_ptr());
|
||||
if (convert != nullptr) {
|
||||
auto defaultPrecisions = LayerTransformation::getDefaultPrecisions();
|
||||
auto el_type = convert->input(0).get_element_type();
|
||||
auto foundIt = std::find(defaultPrecisions.begin(), defaultPrecisions.end(), el_type);
|
||||
if (foundIt == defaultPrecisions.end() &&
|
||||
el_type != element::i4 && el_type != element::u4 &&
|
||||
el_type != element::f32 && el_type != element::f16) {
|
||||
if ((convert->input(0).get_element_type() != element::i8) && (convert->input(0).get_element_type() != element::u8) &&
|
||||
(convert->input(0).get_element_type() != element::i4) && (convert->input(0).get_element_type() != element::u4) &&
|
||||
(convert->output(0).get_element_type() != element::f32)) {
|
||||
return FakeQuantizeDequantization(dataNode, nullptr, subtract, subtractConvert, subtractConstant, multiply, multiplyConstant);
|
||||
}
|
||||
dataNode = convert->get_input_source_output(0);
|
||||
|
@ -1,200 +0,0 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "layer_transformation.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <transformations/init_node_info.hpp>
|
||||
#include <low_precision/assign_and_read_value.hpp>
|
||||
|
||||
#include "common_test_utils/ngraph_test_utils.hpp"
|
||||
#include "lpt_ngraph_functions/common/dequantization_operations.hpp"
|
||||
#include "lpt_ngraph_functions/assign_and_read_value_function.hpp"
|
||||
#include "simple_low_precision_transformer.hpp"
|
||||
#include "low_precision/layer_transformation.hpp"
|
||||
|
||||
|
||||
namespace {
|
||||
using namespace testing;
|
||||
using namespace ngraph::pass;
|
||||
using namespace ngraph;
|
||||
|
||||
class AssignTransformationTestValues {
|
||||
public:
|
||||
class Actual {
|
||||
public:
|
||||
std::vector<float> constantValue;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantization;
|
||||
};
|
||||
|
||||
class Expected {
|
||||
public:
|
||||
std::vector<float> constantValue;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationBefore;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationAfter;
|
||||
};
|
||||
|
||||
TestTransformationParams params;
|
||||
Actual actual;
|
||||
Expected expected;
|
||||
bool FQAfterReadValue;
|
||||
};
|
||||
|
||||
typedef std::tuple <
|
||||
ngraph::PartialShape, // input shape
|
||||
element::Type, // input precision
|
||||
element::Type, // precision before dequantization
|
||||
size_t, // opset version
|
||||
AssignTransformationTestValues // test values
|
||||
> AssignTransformationParams;
|
||||
|
||||
class AssignTransformation : public LayerTransformation, public testing::WithParamInterface<AssignTransformationParams> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
const ngraph::PartialShape inputShape = std::get<0>(GetParam());
|
||||
const element::Type precision = std::get<1>(GetParam());
|
||||
const element::Type precisionBeforeDequantization = std::get<2>(GetParam());
|
||||
const size_t opsetVersion = std::get<3>(GetParam());
|
||||
const AssignTransformationTestValues testValues = std::get<4>(GetParam());
|
||||
low_precision::LayerTransformation::setDefaultPrecisions({
|
||||
ngraph::element::u8, ngraph::element::i8,
|
||||
ngraph::element::u16, ngraph::element::i16,
|
||||
ngraph::element::u32, ngraph::element::i32
|
||||
});
|
||||
actualFunction = ngraph::builder::subgraph::AssignAndReadValueFunction::getOriginal(
|
||||
inputShape,
|
||||
precision,
|
||||
precisionBeforeDequantization,
|
||||
opsetVersion,
|
||||
testValues.FQAfterReadValue,
|
||||
testValues.actual.constantValue,
|
||||
testValues.actual.dequantization);
|
||||
|
||||
SimpleLowPrecisionTransformer transformer;
|
||||
transformer.add<ngraph::pass::low_precision::AssignAndReadValueTransformation, ngraph::opset6::Assign>(actualFunction, testValues.params);
|
||||
transformer.transform(actualFunction);
|
||||
|
||||
referenceFunction = ngraph::builder::subgraph::AssignAndReadValueFunction::getReference(
|
||||
inputShape,
|
||||
precision,
|
||||
precisionBeforeDequantization,
|
||||
opsetVersion,
|
||||
testValues.FQAfterReadValue,
|
||||
testValues.expected.constantValue,
|
||||
testValues.expected.dequantizationBefore,
|
||||
testValues.expected.dequantizationAfter);
|
||||
}
|
||||
|
||||
static std::string getTestCaseName(testing::TestParamInfo<AssignTransformationParams> obj) {
|
||||
const ngraph::PartialShape inputShape = std::get<0>(obj.param);
|
||||
const element::Type precision = std::get<1>(obj.param);
|
||||
const element::Type precisionBeforeDequantization = std::get<2>(obj.param);
|
||||
const size_t opsetVersion = std::get<3>(obj.param);
|
||||
const AssignTransformationTestValues testValues = std::get<4>(obj.param);
|
||||
|
||||
std::ostringstream result;
|
||||
result << toString(testValues.params) << "_" <<
|
||||
inputShape << "_" << precision << "_" <<
|
||||
opsetVersion << "_" << testValues.FQAfterReadValue << "_" <<
|
||||
precisionBeforeDequantization << "_" <<
|
||||
testValues.actual.constantValue << "_" <<
|
||||
testValues.actual.dequantization;
|
||||
return result.str();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(AssignTransformation, CompareFunctions) {
|
||||
actualFunction->validate_nodes_and_infer_types();
|
||||
auto res = compare_functions(referenceFunction, actualFunction, true, true);
|
||||
ASSERT_TRUE(res.first) << res.second;
|
||||
|
||||
ASSERT_TRUE(LayerTransformation::allNamesAreUnique(actualFunction)) << "Not all names are unique";
|
||||
}
|
||||
|
||||
namespace testValues1 {
|
||||
const std::vector<ngraph::PartialShape> inputShapes = {
|
||||
ngraph::PartialShape({ 1, 3, 224, 224 }),
|
||||
};
|
||||
|
||||
const element::TypeVector precisions = {
|
||||
element::f16, element::f32
|
||||
};
|
||||
|
||||
const element::TypeVector precisionsBeforeDequantizations = {
|
||||
element::i8, element::u8,
|
||||
element::i16, element::u16,
|
||||
element::i32, element::u32,
|
||||
};
|
||||
|
||||
const std::vector<size_t> opsetVersions = {
|
||||
3,
|
||||
6
|
||||
};
|
||||
|
||||
const std::vector<AssignTransformationTestValues> testValues = {
|
||||
// general case, no subtract, FQ after ReadValue
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
// ActualValues
|
||||
{
|
||||
{0},
|
||||
{{ngraph::element::f32}, {}, {3.f}}
|
||||
},
|
||||
// ExpectedValues
|
||||
{
|
||||
{0},
|
||||
{{}, {}, {}},
|
||||
{{ngraph::element::f32}, {}, {3.f}}
|
||||
},
|
||||
true
|
||||
},
|
||||
// no FQ after ReadValue
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
// ActualValues
|
||||
{
|
||||
{0},
|
||||
{{ngraph::element::f32}, {}, {3.f}}
|
||||
},
|
||||
// ExpectedValues
|
||||
{
|
||||
{0},
|
||||
{{}, {}, {}},
|
||||
{{ngraph::element::f32}, {}, {3.f}}
|
||||
},
|
||||
false
|
||||
},
|
||||
// non-zero constant
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
// ActualValues
|
||||
{
|
||||
{5},
|
||||
{{ngraph::element::f32}, {}, {3.f}}
|
||||
},
|
||||
// ExpectedValues
|
||||
{
|
||||
{5},
|
||||
{{ngraph::element::f32}, {}, {3.f}},
|
||||
{}
|
||||
},
|
||||
false
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
smoke_LPT,
|
||||
AssignTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(inputShapes),
|
||||
::testing::ValuesIn(precisions),
|
||||
::testing::ValuesIn(precisionsBeforeDequantizations),
|
||||
::testing::ValuesIn(opsetVersions),
|
||||
::testing::ValuesIn(testValues)),
|
||||
AssignTransformation::getTestCaseName);
|
||||
} // namespace testValues1
|
||||
} // namespace
|
@ -24,10 +24,6 @@ public:
|
||||
void add(const TestTransformationParams& params) {
|
||||
commonGraphRewrite->add_matcher<T>(TestTransformationParams::toParams(params));
|
||||
}
|
||||
template <class T, class Operation>
|
||||
void add(const std::shared_ptr<ngraph::Function> function, const TestTransformationParams& params) {
|
||||
commonGraphRewrite->add_matcher<T>(function, TestTransformationParams::toParams(params));
|
||||
}
|
||||
|
||||
void transform(std::shared_ptr<ngraph::Function>& function);
|
||||
bool run_on_model(const std::shared_ptr<ngraph::Function>& m) override;
|
||||
|
@ -1,55 +0,0 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "low_precision_transformations/assign_and_read_value_transformation.hpp"
|
||||
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
const std::vector<ngraph::element::Type> netPrecisions = {
|
||||
ngraph::element::f32,
|
||||
// ngraph::element::f16
|
||||
};
|
||||
|
||||
const std::vector<size_t> opsetVersions = {
|
||||
// 3, // no evaluate for opset 3 in ngraph
|
||||
6
|
||||
};
|
||||
|
||||
const std::vector<ngraph::pass::low_precision::LayerTransformation::Params> trasformationParamValues = {
|
||||
LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams(),
|
||||
LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(false),
|
||||
};
|
||||
|
||||
const std::vector<LayerTestsDefinitions::AssignAndReadValueTransformationParam> params{
|
||||
// u8
|
||||
{
|
||||
{ 256ul, ngraph::Shape{ 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 12.8f } },
|
||||
},
|
||||
// u16
|
||||
{
|
||||
{ 65536ul, ngraph::Shape{ 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 12.8f } },
|
||||
},
|
||||
// u32
|
||||
{
|
||||
{ 4294967296ul, ngraph::Shape{ 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 12.8f } },
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_LPT, AssignAndReadValueTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::Values(ngraph::PartialShape({ 1, 3, 16, 16 })),
|
||||
::testing::ValuesIn(opsetVersions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU),
|
||||
::testing::ValuesIn(trasformationParamValues),
|
||||
::testing::ValuesIn(params)),
|
||||
AssignAndReadValueTransformation::getTestCaseName);
|
||||
|
||||
} // namespace
|
@ -1,55 +0,0 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "low_precision_transformations/assign_and_read_value_transformation.hpp"
|
||||
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
const std::vector<ngraph::element::Type> netPrecisions = {
|
||||
ngraph::element::f32,
|
||||
// ngraph::element::f16
|
||||
};
|
||||
|
||||
const std::vector<size_t> opsetVersions = {
|
||||
// 3, // no evaluate for opset 3 in ngraph
|
||||
// 6 // not supported on GPU
|
||||
};
|
||||
|
||||
const std::vector<ngraph::pass::low_precision::LayerTransformation::Params> trasformationParamValues = {
|
||||
LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams(),
|
||||
LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(false),
|
||||
};
|
||||
|
||||
const std::vector<LayerTestsDefinitions::AssignAndReadValueTransformationParam> params{
|
||||
// u8
|
||||
{
|
||||
{ 256ul, ngraph::Shape{ 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 12.8f } },
|
||||
},
|
||||
// u16
|
||||
{
|
||||
{ 65536ul, ngraph::Shape{ 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 12.8f } },
|
||||
},
|
||||
// u32
|
||||
{
|
||||
{ 4294967296ul, ngraph::Shape{ 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 12.8f } },
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_LPT, AssignAndReadValueTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::Values(ngraph::PartialShape({ 1, 3, 16, 16 })),
|
||||
::testing::ValuesIn(opsetVersions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_GPU),
|
||||
::testing::ValuesIn(trasformationParamValues),
|
||||
::testing::ValuesIn(params)),
|
||||
AssignAndReadValueTransformation::getTestCaseName);
|
||||
|
||||
} // namespace
|
@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared_test_classes/base/low_precision_transformations/layer_transformation.hpp"
|
||||
#include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp"
|
||||
#include "lpt_ngraph_functions/common/dequantization_operations.hpp"
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
class AssignAndReadValueTransformationParam {
|
||||
public:
|
||||
ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantize;
|
||||
};
|
||||
|
||||
typedef std::tuple <
|
||||
ngraph::element::Type, // input precision
|
||||
ngraph::PartialShape, // input shape
|
||||
size_t, // opset version
|
||||
std::string, // device
|
||||
ngraph::pass::low_precision::LayerTransformation::Params, // transformation params
|
||||
AssignAndReadValueTransformationParam // test params
|
||||
> AssignAndReadValueTransformationParams;
|
||||
|
||||
class AssignAndReadValueTransformation :
|
||||
public testing::WithParamInterface<AssignAndReadValueTransformationParams>,
|
||||
public LayerTestsUtils::LayerTransformation {
|
||||
public:
|
||||
static std::string getTestCaseName(const testing::TestParamInfo<AssignAndReadValueTransformationParams>& obj);
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
@ -1,49 +0,0 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "low_precision_transformations/assign_and_read_value_transformation.hpp"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
|
||||
#include "lpt_ngraph_functions/assign_and_read_value_function.hpp"
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
std::string AssignAndReadValueTransformation::getTestCaseName(const testing::TestParamInfo<AssignAndReadValueTransformationParams>& obj) {
|
||||
ngraph::element::Type netPrecision;
|
||||
ngraph::PartialShape inputShape;
|
||||
size_t opset;
|
||||
std::string targetDevice;
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
AssignAndReadValueTransformationParam param;;
|
||||
std::tie(netPrecision, inputShape, opset, targetDevice, params, param) = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
result << getTestCaseNameByParams(netPrecision, inputShape, targetDevice, params) << "_" <<
|
||||
param.fakeQuantize << "_" << opset;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void AssignAndReadValueTransformation::SetUp() {
|
||||
ngraph::element::Type netPrecision;
|
||||
ngraph::PartialShape inputShape;
|
||||
size_t opset;
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
AssignAndReadValueTransformationParam param;
|
||||
std::tie(netPrecision, inputShape, opset, targetDevice, params, param) = this->GetParam();
|
||||
|
||||
function = ngraph::builder::subgraph::AssignAndReadValueFunction::getOriginal(
|
||||
netPrecision,
|
||||
inputShape,
|
||||
param.fakeQuantize,
|
||||
opset);
|
||||
}
|
||||
|
||||
TEST_P(AssignAndReadValueTransformation, CompareWithRefImpl) {
|
||||
Run();
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
@ -1,46 +0,0 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp"
|
||||
#include "lpt_ngraph_functions/common/dequantization_operations.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
namespace subgraph {
|
||||
|
||||
class AssignAndReadValueFunction {
|
||||
public:
|
||||
static std::shared_ptr<ngraph::Function> getOriginal(
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const element::Type& inputPrecision,
|
||||
const ngraph::element::Type precisionBeforeDequantization,
|
||||
const size_t opsetVersion,
|
||||
const bool FQAfterReadValue,
|
||||
const std::vector<float>& constantValue,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& dequantization);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getOriginal(
|
||||
const ngraph::element::Type originalFunctionPrecision,
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantize,
|
||||
const size_t opsetVersion);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getReference(
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const element::Type& inputPrecision,
|
||||
const ngraph::element::Type precisionBeforeDequantization,
|
||||
const size_t opsetVersion,
|
||||
const bool FQAfterReadValue,
|
||||
const std::vector<float>& constantValue,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& dequantizationBefore,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& dequantizationAfter);
|
||||
};
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
@ -1,185 +0,0 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
|
||||
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
#include "ngraph_functions/subgraph_builders.hpp"
|
||||
#include "openvino/op/util/variable.hpp"
|
||||
#include <openvino/op/util/assign_base.hpp>
|
||||
|
||||
#include "lpt_ngraph_functions/common/builders.hpp"
|
||||
#include "lpt_ngraph_functions/assign_and_read_value_function.hpp"
|
||||
#include "low_precision/network_helper.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
namespace subgraph {
|
||||
|
||||
std::shared_ptr<ngraph::Function> AssignAndReadValueFunction::getOriginal(
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const element::Type& inputPrecision,
|
||||
const ngraph::element::Type precisionBeforeDequantization,
|
||||
const size_t opsetVersion,
|
||||
const bool FQAfterReadValue,
|
||||
const std::vector<float>& constantValue,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& dequantization) {
|
||||
const auto input = std::make_shared<ngraph::opset1::Parameter>(inputPrecision, inputShape);
|
||||
const auto defaultConstant = std::make_shared<opset1::Constant>(inputPrecision, inputShape.get_shape(), constantValue);
|
||||
const auto variable = std::make_shared<Variable>(VariableInfo{inputShape.get_shape(), inputPrecision, "id"});
|
||||
std::shared_ptr<Node> readValue;
|
||||
if (opsetVersion == 6) {
|
||||
readValue = std::make_shared<opset6::ReadValue>(defaultConstant, variable);
|
||||
} else if (opsetVersion == 3) {
|
||||
readValue = std::make_shared<opset3::ReadValue>(defaultConstant, "id");
|
||||
} else {
|
||||
throw std::runtime_error("Unknown opset version");
|
||||
}
|
||||
std::shared_ptr<Node> lastNode = readValue;
|
||||
if (FQAfterReadValue) {
|
||||
lastNode = builder::subgraph::makeFakeQuantize(
|
||||
lastNode,
|
||||
element::f32,
|
||||
FakeQuantizeOnData{256ul, Shape{}, {0}, {2.55f}, {0}, {2.55f}});
|
||||
}
|
||||
const auto add = std::make_shared<opset1::Add>(lastNode, input);
|
||||
const auto FQAfterAdd = builder::subgraph::makeFakeQuantizeTypeRelaxed(
|
||||
add,
|
||||
element::f32,
|
||||
FakeQuantizeOnData{256ul, Shape{}, {0}, {2.55f}, {0}, {2.55f}, precisionBeforeDequantization});
|
||||
auto deqStructure = dequantization;
|
||||
deqStructure.multiply.outPrecision = inputPrecision;
|
||||
const auto dequantizationOp = makeDequantization(FQAfterAdd, deqStructure);
|
||||
std::shared_ptr<Node> assign;
|
||||
if (opsetVersion == 6) {
|
||||
assign = std::make_shared<opset6::Assign>(dequantizationOp, variable);
|
||||
} else {
|
||||
assign = std::make_shared<opset3::Assign>(dequantizationOp, "id");
|
||||
}
|
||||
assign->add_control_dependency(readValue);
|
||||
add->set_friendly_name("output");
|
||||
|
||||
ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(add) };
|
||||
ngraph::SinkVector sinks{ as_type_ptr<ov::op::Sink>(assign) };
|
||||
return std::make_shared<ngraph::Function>(results, sinks, ngraph::ParameterVector{ input }, "AssignAndReadValueFunction");
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> AssignAndReadValueFunction::getOriginal(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantize,
|
||||
const size_t opsetVersion) {
|
||||
const auto input = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
|
||||
const auto defaultConstant = std::make_shared<opset1::Constant>(precision, inputShape.get_shape(), std::vector<float>{0});
|
||||
const auto variable = std::make_shared<Variable>(VariableInfo{inputShape.get_shape(), precision, "id"});
|
||||
std::shared_ptr<Node> readValue;
|
||||
if (opsetVersion == 6) {
|
||||
readValue = std::make_shared<opset6::ReadValue>(defaultConstant, variable);
|
||||
} else if (opsetVersion == 3) {
|
||||
readValue = std::make_shared<opset3::ReadValue>(defaultConstant, "id");
|
||||
} else {
|
||||
throw std::runtime_error("Unknown opset version");
|
||||
}
|
||||
std::shared_ptr<Node> lastNode = readValue;
|
||||
lastNode = builder::subgraph::makeFakeQuantize(
|
||||
lastNode,
|
||||
element::f32,
|
||||
FakeQuantizeOnData{256ul, Shape{}, {0}, {2.55f}, {0}, {2.55f}});
|
||||
const auto add = std::make_shared<opset1::Add>(lastNode, input);
|
||||
const auto FQAfterAdd = fakeQuantize.empty() ? nullptr :
|
||||
ngraph::builder::makeFakeQuantize(
|
||||
add,
|
||||
precision,
|
||||
fakeQuantize.quantizationLevel,
|
||||
fakeQuantize.constantShape,
|
||||
fakeQuantize.inputLowValues,
|
||||
fakeQuantize.inputHighValues,
|
||||
fakeQuantize.outputLowValues,
|
||||
fakeQuantize.outputHighValues);
|
||||
std::shared_ptr<Node> assign;
|
||||
if (opsetVersion == 6) {
|
||||
assign = std::make_shared<opset6::Assign>(FQAfterAdd, variable);
|
||||
} else {
|
||||
assign = std::make_shared<opset3::Assign>(FQAfterAdd, "id");
|
||||
}
|
||||
assign->add_control_dependency(readValue);
|
||||
add->set_friendly_name("output");
|
||||
|
||||
ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(add) };
|
||||
ngraph::SinkVector sinks{ as_type_ptr<ov::op::Sink>(assign) };
|
||||
return std::make_shared<ngraph::Function>(results, sinks, ngraph::ParameterVector{ input }, "AssignAndReadValueFunction");
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> AssignAndReadValueFunction::getReference(
|
||||
const ngraph::PartialShape& inputShape,
|
||||
const element::Type& inputPrecision,
|
||||
const ngraph::element::Type precisionBeforeDequantization,
|
||||
const size_t opsetVersion,
|
||||
const bool FQAfterReadValue,
|
||||
const std::vector<float>& constantValue,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& dequantizationBefore,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& dequantizationAfter) {
|
||||
const auto input = std::make_shared<ngraph::opset1::Parameter>(inputPrecision, inputShape);
|
||||
auto constantPrecision = precisionBeforeDequantization;
|
||||
if (constantValue != std::vector<float>{0}) {
|
||||
constantPrecision = inputPrecision;
|
||||
}
|
||||
const auto defaultConstant = std::make_shared<opset1::Constant>(constantPrecision, inputShape.get_shape(), constantValue);
|
||||
const auto variable = std::make_shared<Variable>(VariableInfo{inputShape.get_shape(), constantPrecision, "id"});
|
||||
std::shared_ptr<Node> readValue;
|
||||
if (opsetVersion == 6) {
|
||||
readValue = std::make_shared<opset6::ReadValue>(defaultConstant, variable);
|
||||
} else if (opsetVersion == 3) {
|
||||
readValue = std::make_shared<opset3::ReadValue>(defaultConstant, "id");
|
||||
} else {
|
||||
throw std::runtime_error("Unknown opset version");
|
||||
}
|
||||
std::shared_ptr<Node> lastNode = readValue;
|
||||
|
||||
auto deqStructureAfter = dequantizationAfter;
|
||||
if (FQAfterReadValue) {
|
||||
DequantizationOperations tempDequantization;
|
||||
tempDequantization.convert = dequantizationAfter.convert;
|
||||
tempDequantization.subtract = dequantizationAfter.subtract;
|
||||
lastNode = makeDequantization(lastNode, tempDequantization);
|
||||
} else {
|
||||
deqStructureAfter.multiply.outPrecision = inputPrecision;
|
||||
lastNode = makeDequantization(lastNode, deqStructureAfter);
|
||||
}
|
||||
|
||||
if (FQAfterReadValue) {
|
||||
lastNode = builder::subgraph::makeFakeQuantizeTypeRelaxed(
|
||||
lastNode,
|
||||
element::f32,
|
||||
FakeQuantizeOnData{256ul, Shape{}, {0}, {2.55f / dequantizationAfter.multiply.values[0]}, {0}, {2.55f}, inputPrecision});
|
||||
}
|
||||
const auto add = std::make_shared<opset1::Add>(lastNode, input);
|
||||
const auto FQAfterAdd = builder::subgraph::makeFakeQuantizeTypeRelaxed(
|
||||
add,
|
||||
element::f32,
|
||||
FakeQuantizeOnData{256ul, Shape{}, {0}, {2.55f}, {0}, {2.55f}, precisionBeforeDequantization});
|
||||
|
||||
auto deqStructureBefore = dequantizationBefore;
|
||||
deqStructureBefore.multiply.outPrecision = inputPrecision;
|
||||
const auto dequantizationBeforeStructure = makeDequantization(FQAfterAdd, deqStructureBefore);
|
||||
std::shared_ptr<Node> assign;
|
||||
if (opsetVersion == 6) {
|
||||
assign = std::make_shared<opset6::Assign>(dequantizationBeforeStructure, variable);
|
||||
} else {
|
||||
assign = std::make_shared<opset3::Assign>(dequantizationBeforeStructure, "id");
|
||||
}
|
||||
assign->add_control_dependency(readValue);
|
||||
add->set_friendly_name("output");
|
||||
|
||||
ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(add) };
|
||||
ngraph::SinkVector sinks{ as_type_ptr<ov::op::Sink>(assign) };
|
||||
return std::make_shared<ngraph::Function>(results, sinks, ngraph::ParameterVector{ input }, "AssignAndReadValueFunction");
|
||||
}
|
||||
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
Loading…
Reference in New Issue
Block a user