[LPT] AddTransformation fix (#17076)

* [LPT] AddTransformation: constants on 0's input support

* AddTransformation: new test instances

* codestyle
This commit is contained in:
Vladislav Golubev 2023-04-24 13:15:01 +02:00 committed by GitHub
parent a3f14366d9
commit f410658d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 37 deletions

View File

@ -60,9 +60,9 @@ bool EltwiseBaseTransformation::canBeTransformed(const TransformationContext& co
}
static bool isTargetType(const std::shared_ptr<Node> node) {
return ov::is_type<opset1::Convolution>(node) ||
ov::is_type<opset1::GroupConvolution>(node) ||
ov::is_type<opset1::MatMul>(node);
return node != nullptr && (ov::is_type<opset1::Convolution>(node) ||
ov::is_type<opset1::GroupConvolution>(node) ||
ov::is_type<opset1::MatMul>(node));
}
static std::shared_ptr<Node> getDataParent(const std::shared_ptr<Node> branchData) {
@ -72,30 +72,38 @@ static std::shared_ptr<Node> getDataParent(const std::shared_ptr<Node> branchDat
}
if (ov::marked_as_bias(parent)) {
const auto bias_parent = parent->get_input_node_shared_ptr(0);
// target node just before bias
if (isTargetType(bias_parent)) {
return bias_parent;
}
// between target node and bias are placed some DQ operations
const auto dq = NetworkHelper::getDequantization(parent->get_input_node_shared_ptr(0));
const auto data_node = dq.data.get_node_shared_ptr();
if (isTargetType(data_node)) {
return data_node;
// we need to check both inputs in order to handle the case with constant on 0's input
for (size_t i = 0; i < parent->get_input_size(); ++i) {
const auto bias_parent = parent->get_input_node_shared_ptr(i);
// target node just before bias
if (isTargetType(bias_parent)) {
return bias_parent;
}
// between target node and bias are placed some DQ operations
const auto dq = NetworkHelper::getDequantization(bias_parent);
const auto data_node = dq.data.get_node_shared_ptr();
if (isTargetType(data_node)) {
return data_node;
}
}
}
return parent;
}
static bool isBranchHaveMultipleConsumers(const std::shared_ptr<Node> branchData, const std::shared_ptr<Node> branchDataParent) {
auto several_consumers = [](const std::shared_ptr<ov::Node>& node) {
return node->get_output_size() != 1 || node->get_output_target_inputs(0).size() != 1;
};
auto parent = branchData;
while (parent != branchDataParent) {
if ((parent->get_output_size() != 1ul) || (parent->get_output_target_inputs(0).size() != 1ul)) {
if (several_consumers(parent)) {
return true;
}
parent = parent->get_input_node_shared_ptr(0);
const auto new_parent = parent->get_input_node_shared_ptr(0);
parent = !ov::is_type<opset1::Constant>(new_parent) ? new_parent : parent->get_input_node_shared_ptr(1);
}
return (parent->get_output_size() != 1ul) || (parent->get_output_target_inputs(0).size() != 1ul);
return several_consumers(parent);
}
// return branch index with FP32 precision after eltwise transformation

View File

@ -69,6 +69,7 @@ public:
Actual actual;
Expected expected;
std::string additionalLayer;
std::string postops_configuration;
};
typedef std::tuple<ngraph::element::Type,
@ -94,7 +95,8 @@ public:
testValues.actual.dequantization2,
testValues.constInput,
testValues.actual.constValues,
testValues.additionalLayer);
testValues.additionalLayer,
testValues.postops_configuration);
SimpleLowPrecisionTransformer transform;
transform.add<ngraph::pass::low_precision::AddTransformation, ngraph::opset1::Add>(testValues.params);
@ -120,7 +122,8 @@ public:
testValues.constInput == -1 ? -1 : 1,
testValues.expected.constValues,
testValues.additionalLayer,
testValues.expected.operationType);
testValues.expected.operationType,
testValues.postops_configuration);
}
static std::string getTestCaseName(testing::TestParamInfo<AddTransformationParams> obj) {
@ -133,7 +136,8 @@ public:
<< "_" << testValues.actual.precision1 << "_" << testValues.actual.dequantization1 << "_"
<< testValues.actual.precision2 << "_" << testValues.actual.dequantization2 << "_"
<< testValues.constInput << "_" << testValues.actual.constValues << "_" << testValues.additionalLayer
<< "_" << (testValues.params.updatePrecisions ? "true" : "false");
<< "_" << testValues.postops_configuration << "_"
<< (testValues.params.updatePrecisions ? "true" : "false");
return result.str();
}
};
@ -439,6 +443,23 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
{{}, {}, {10.f}},
{}},
"convolution"},
// convolution before FQ
{false,
-1,
LayerTransformation::createParamsU8I8(),
{ngraph::element::u8,
{{ngraph::element::f32}, {7.f}, {10.f}},
ngraph::element::u8,
{{ngraph::element::f32}, {3.f}, {5.f}},
{}},
{ngraph::element::u8,
{{}, {}, {}},
ngraph::element::u8,
{{ngraph::element::f32}, {17.f}, {0.5f}},
{{}, {}, {10.f}},
{}},
"convolution",
"bias_on_zero_input"},
// convolution with multiple consumers before FQ ( FP32 on other branch due to possible quantize fusing )
{false,
-1,

View File

@ -70,7 +70,8 @@ public:
const ngraph::builder::subgraph::DequantizationOperations& dequantization2,
const int constInput,
const std::vector<float>& constValues,
const std::string& additionalLayer);
const std::string& additionalLayer,
const std::string& postops_configuration = "");
static std::shared_ptr<ngraph::Function> getOriginal(
const ngraph::element::Type precision,
@ -93,7 +94,8 @@ public:
const int constInput,
const std::vector<float>& constValues,
const std::string& additionalLayer,
const std::string& operationType);
const std::string& operationType,
const std::string& postops_configuration = "");
};
} // namespace subgraph

View File

@ -18,6 +18,28 @@ namespace ngraph {
namespace builder {
namespace subgraph {
namespace {
std::shared_ptr<Node> configure_postops(const std::shared_ptr<Node>& parent,
const ov::element::Type& precision,
const std::string& postops_configuration) {
std::shared_ptr<Node> res = parent;
if (postops_configuration.empty() || postops_configuration == "bias") {
auto bias = opset1::Constant::create(precision, { 1, 1, 1, 1 }, {1.f});
res = std::make_shared<opset1::Add>(res, bias);
} else if (postops_configuration == "bias_on_zero_input") {
auto bias = opset1::Constant::create(precision, { 1, 1, 1, 1 }, {1.f});
res = std::make_shared<opset1::Add>(bias, res);
} else {
return parent;
}
return ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
res,
precision,
{256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
}
} // namespace
std::shared_ptr<ngraph::Function> AddFunction::getOriginal(
const ngraph::element::Type precision,
const ngraph::PartialShape& inputShape1,
@ -30,7 +52,8 @@ std::shared_ptr<ngraph::Function> AddFunction::getOriginal(
const ngraph::builder::subgraph::DequantizationOperations& dequantization2,
const int constInput,
const std::vector<float>& constValues,
const std::string& additionalLayer) {
const std::string& additionalLayer,
const std::string& postops_configuration) {
std::shared_ptr<ngraph::Node> input1;
std::shared_ptr<ngraph::Node> parent1;
if (constInput == 0) {
@ -113,13 +136,7 @@ std::shared_ptr<ngraph::Function> AddFunction::getOriginal(
ngraph::Strides{ 1, 1 });
}
if (additionalLayer != "") {
parent = std::make_shared<ngraph::opset1::Add>(
parent,
std::make_shared<ngraph::opset1::Constant>(precision, Shape{ 1, 1, 1, 1 }, std::vector<float>{1.f}));
parent = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
parent,
precision,
{256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
parent = configure_postops(parent, precision, postops_configuration);
}
auto dequantizationStructure2 = dequantization2;
@ -203,7 +220,8 @@ std::shared_ptr<ngraph::Function> AddFunction::getReference(
const int constInputIndex,
const std::vector<float>& constValues,
const std::string& additionalLayer,
const std::string& operationType) {
const std::string& operationType,
const std::string& postops_configuration) {
std::shared_ptr<ngraph::Node> input1;
std::shared_ptr<ngraph::Node> parent1;
if (constInputIndex == 0) {
@ -282,13 +300,7 @@ std::shared_ptr<ngraph::Function> AddFunction::getReference(
ngraph::Strides{ 1, 1 });
}
if (additionalLayer != "") {
parent = std::make_shared<ngraph::opset1::Add>(
parent,
std::make_shared<ngraph::opset1::Constant>(precision, Shape{ 1, 1, 1, 1 }, std::vector<float>{1.f}));
parent = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
parent,
precision,
{256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
parent = configure_postops(parent, precision, postops_configuration);
}
auto dequantizationStructure2 = dequantization2;