From b4972a835a51c37922317622c37dd9f0592dadd8 Mon Sep 17 00:00:00 2001 From: Edward Shogulin Date: Mon, 21 Mar 2022 00:55:26 +0300 Subject: [PATCH] [CPU] Code generation: FakeQuantize decomposition & common transformations - tests #2 --- .../pass/fake_quantize_decomposition_test.cpp | 58 ++++++ ...p => fake_quantize_decomposition_test.cpp} | 8 +- ...p => fake_quantize_decomposition_test.hpp} | 2 +- ...p => fake_quantize_decomposition_test.cpp} | 61 ++---- .../include/fake_quantize_function.hpp | 40 ++++ .../src/fake_quantize_function.cpp | 191 ++++++++++++++++++ 6 files changed, 306 insertions(+), 54 deletions(-) create mode 100644 src/tests/functional/inference_engine/snippets/src/pass/fake_quantize_decomposition_test.cpp rename src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/{codegen_quantized.cpp => fake_quantize_decomposition_test.cpp} (92%) rename src/tests/functional/plugin/shared/include/subgraph_tests/{codegen_quantized.hpp => fake_quantize_decomposition_test.hpp} (94%) rename src/tests/functional/plugin/shared/src/snippets/{codegen_quantized.cpp => fake_quantize_decomposition_test.cpp} (52%) create mode 100644 src/tests/ngraph_helpers/snippets_ngraph_functions/include/fake_quantize_function.hpp create mode 100644 src/tests/ngraph_helpers/snippets_ngraph_functions/src/fake_quantize_function.cpp diff --git a/src/tests/functional/inference_engine/snippets/src/pass/fake_quantize_decomposition_test.cpp b/src/tests/functional/inference_engine/snippets/src/pass/fake_quantize_decomposition_test.cpp new file mode 100644 index 00000000000000..34c9f290726b70 --- /dev/null +++ b/src/tests/functional/inference_engine/snippets/src/pass/fake_quantize_decomposition_test.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "common_test_utils/ngraph_test_utils.hpp" +#include "snippets/pass/common_optimizations.hpp" +#include "snippets/pass/constant_folding.hpp" +#include "fake_quantize_function.hpp" + +// TODO: to dbug only +#include "snippets/op/subgraph.hpp" + +namespace ov { +namespace test { +namespace snippets { + +namespace { +std::shared_ptr getSubgraph(const std::shared_ptr& f) { + std::shared_ptr subgraph; + for (const auto& op : f->get_ops()) { + auto tmp_subgraph = as_type_ptr(op); + if (tmp_subgraph != nullptr) { + NGRAPH_CHECK(subgraph == nullptr, "function contains more than one subgraph"); + subgraph = tmp_subgraph; + } + } + return subgraph; +} +} // namespace + +class FakeQuantizeDecompositionTest : public TransformationTestsF { +public: + void register_passes() { + manager.register_pass(); + manager.register_pass(); + } + + void TearDown() override { + TransformationTestsF::TearDown(); + + auto body = getSubgraph(function)->get_body(); + auto body_ref = getSubgraph(function_ref)->get_body(); + auto res = comparator.compare(body, body_ref); + ASSERT_TRUE(res.valid) << res.message; + } +}; + +TEST_F(FakeQuantizeDecompositionTest, smoke_Snippets_FakeQuantizeDecomposition) { + function = FakeQuantizeFunction::getSubgraphWithFakeQuantize({1, 3, 299, 299}, element::f32, {{}, {}, {}, {}}, true); + function_ref = FakeQuantizeFunction::getSubgraphWithDecomposedFakeQuantize({1, 3, 299, 299}, element::f32, {{}, {}, {}, {}}, true); + register_passes(); +} + +} // namespace snippets +} // namespace test +} // namespace ov \ No newline at end of file diff --git a/src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/codegen_quantized.cpp b/src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/fake_quantize_decomposition_test.cpp similarity index 92% rename from src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/codegen_quantized.cpp rename to src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/fake_quantize_decomposition_test.cpp index 897817ad0852c7..e772b7e221db6c 100644 --- a/src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/codegen_quantized.cpp +++ b/src/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/fake_quantize_decomposition_test.cpp @@ -5,7 +5,7 @@ #include -#include "subgraph_tests/codegen_quantized.hpp" +#include "subgraph_tests/fake_quantize_decomposition_test.hpp" using namespace LayerTestsDefinitions; @@ -88,9 +88,9 @@ const std::vector testValues = { }; INSTANTIATE_TEST_SUITE_P( - smoke_CodeGeneration, - CodegenQuantized, + smoke_Snippets, + FakeQuantizeDecompositionTest, ::testing::ValuesIn(testValues), - CodegenQuantized::getTestCaseName); + FakeQuantizeDecompositionTest::getTestCaseName); } // namespace diff --git a/src/tests/functional/plugin/shared/include/subgraph_tests/codegen_quantized.hpp b/src/tests/functional/plugin/shared/include/subgraph_tests/fake_quantize_decomposition_test.hpp similarity index 94% rename from src/tests/functional/plugin/shared/include/subgraph_tests/codegen_quantized.hpp rename to src/tests/functional/plugin/shared/include/subgraph_tests/fake_quantize_decomposition_test.hpp index c042bb9a35a9b9..b85769dc987059 100644 --- a/src/tests/functional/plugin/shared/include/subgraph_tests/codegen_quantized.hpp +++ b/src/tests/functional/plugin/shared/include/subgraph_tests/fake_quantize_decomposition_test.hpp @@ -51,7 +51,7 @@ class TestValues { ExpectedValues expected; }; -class CodegenQuantized : public testing::WithParamInterface, +class FakeQuantizeDecompositionTest : public testing::WithParamInterface, virtual public LayerTestsUtils::LayerTestsCommon { public: static std::string getTestCaseName(testing::TestParamInfo obj); diff --git a/src/tests/functional/plugin/shared/src/snippets/codegen_quantized.cpp b/src/tests/functional/plugin/shared/src/snippets/fake_quantize_decomposition_test.cpp similarity index 52% rename from src/tests/functional/plugin/shared/src/snippets/codegen_quantized.cpp rename to src/tests/functional/plugin/shared/src/snippets/fake_quantize_decomposition_test.cpp index 0b96ec5a7ed20f..af7a297ed9fe7b 100644 --- a/src/tests/functional/plugin/shared/src/snippets/codegen_quantized.cpp +++ b/src/tests/functional/plugin/shared/src/snippets/fake_quantize_decomposition_test.cpp @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "subgraph_tests/codegen_quantized.hpp" +#include "subgraph_tests/fake_quantize_decomposition_test.hpp" #include #include @@ -12,10 +12,11 @@ #include #include "ngraph_ops/type_relaxed.hpp" +#include "fake_quantize_function.hpp" namespace LayerTestsDefinitions { -std::string CodegenQuantized::getTestCaseName(testing::TestParamInfo obj) { +std::string FakeQuantizeDecompositionTest::getTestCaseName(testing::TestParamInfo obj) { std::ostringstream result; result << "IS=" << CommonTestUtils::vec2str(obj.param.actual.inputShape) << "_"; result << "netPRC=" << obj.param.actual.modelType << "_"; @@ -27,7 +28,7 @@ std::string CodegenQuantized::getTestCaseName(testing::TestParamInfo return result.str(); } -void CodegenQuantized::GenerateInputs() { +void FakeQuantizeDecompositionTest::GenerateInputs() { inputs.clear(); const auto& inputsInfo = executableNetwork.GetInputsInfo(); const auto& functionParams = function->get_parameters(); @@ -51,56 +52,18 @@ void CodegenQuantized::GenerateInputs() { } } -void CodegenQuantized::SetUp() { +void FakeQuantizeDecompositionTest::SetUp() { auto& values = this->GetParam(); targetDevice = values.actual.targetDevice; - const auto parameter = std::make_shared(values.actual.inputType, ngraph::Shape{values.actual.inputShape}); - parameter->set_friendly_name("parameter"); - - const auto convert1 = std::make_shared(parameter, ov::element::u8); - convert1->set_friendly_name("convert1"); - - const auto relu1 = std::make_shared(convert1); - relu1->set_friendly_name("relu1"); - - const auto convert2 = std::make_shared(relu1, ov::element::f32); - convert2->set_friendly_name("convert2"); - - const auto slope2 = std::make_shared(ov::element::f32, ov::Shape{}, std::vector{-1.f}); - const auto relu2 = std::make_shared(convert2, slope2); - relu2->set_friendly_name("relu2"); - - 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 values(size); - for (auto i = 0; i < size; ++i) { - values[i] = static_cast(initialValue + i); - } - auto constant = std::make_shared(precision, shape, values); - constant->set_friendly_name(name); - return constant; - }; - - const auto fakeQuantize = std::make_shared( - relu2, - generate(values.actual.inputType, values.actual.fakeQuantizeShapes[0], values.actual.zeroPoint, "inputLow"), - generate(values.actual.inputType, values.actual.fakeQuantizeShapes[1], 20.f, "inputHigh"), - generate(values.actual.inputType, values.actual.fakeQuantizeShapes[2], values.actual.zeroPoint, "outputLow"), - generate(values.actual.inputType, values.actual.fakeQuantizeShapes[3], 20.f, "outputHigh"), - 256ul); - fakeQuantize->set_friendly_name("fakeQuantize"); - - const auto relu3 = std::make_shared(fakeQuantize); - relu3->set_friendly_name("relu3"); - - const auto result = std::make_shared(relu3); - result->set_friendly_name("result"); - - function = std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{parameter}, "CodegenQuantized"); + function = ov::test::snippets::FakeQuantizeFunction::get( + values.actual.inputShape, + values.actual.inputType, + values.actual.fakeQuantizeShapes, + values.actual.zeroPoint); } -void CodegenQuantized::Run() { +void FakeQuantizeDecompositionTest::Run() { LayerTestsCommon::Run(); auto& values = this->GetParam(); @@ -126,7 +89,7 @@ void CodegenQuantized::Run() { } } -TEST_P(CodegenQuantized, CompareWithRefImpl) { +TEST_P(FakeQuantizeDecompositionTest, CompareWithRefImpl) { Run(); }; diff --git a/src/tests/ngraph_helpers/snippets_ngraph_functions/include/fake_quantize_function.hpp b/src/tests/ngraph_helpers/snippets_ngraph_functions/include/fake_quantize_function.hpp new file mode 100644 index 00000000000000..fd21831764a340 --- /dev/null +++ b/src/tests/ngraph_helpers/snippets_ngraph_functions/include/fake_quantize_function.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/ngraph.hpp" + +namespace ov { +namespace test { +namespace snippets { + +class FakeQuantizeFunction { +public: + // Parameter => [service ops for workaround to add FakeQuantize to Snippet] => FakeQuantize => Result + static std::shared_ptr get( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint); + + // Parameter => Subgraph (Parameter => FakeQuantize => Result) => Result + static std::shared_ptr getSubgraphWithFakeQuantize( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint); + + // Parameter => Subgraph (Parameter => element-wise ops from FakeQuantize decomposition results => Result) => Result + static std::shared_ptr getSubgraphWithDecomposedFakeQuantize( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint); +}; + +} // namespace snippets +} // namespace test +} // namespace ov + diff --git a/src/tests/ngraph_helpers/snippets_ngraph_functions/src/fake_quantize_function.cpp b/src/tests/ngraph_helpers/snippets_ngraph_functions/src/fake_quantize_function.cpp new file mode 100644 index 00000000000000..cde2f91914fd2b --- /dev/null +++ b/src/tests/ngraph_helpers/snippets_ngraph_functions/src/fake_quantize_function.cpp @@ -0,0 +1,191 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "fake_quantize_function.hpp" +#include "common_test_utils/data_utils.hpp" +#include +#include +#include "ngraph_functions/builders.hpp" + +namespace ov { +namespace test { +namespace snippets { + +namespace { +std::shared_ptr getFakeQuantize( + const std::shared_ptr& parent, + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint) { + 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 values(size); + for (auto i = 0; i < size; ++i) { + values[i] = static_cast(initialValue + i); + } + auto constant = std::make_shared(precision, shape, values); + constant->set_friendly_name(name); + return constant; + }; + + const auto fakeQuantize = std::make_shared( + parent, + generate(inputType, fakeQuantizeShapes[0], zeroPoint, "inputLow"), + generate(inputType, fakeQuantizeShapes[1], 20.f, "inputHigh"), + generate(inputType, fakeQuantizeShapes[2], zeroPoint, "outputLow"), + generate(inputType, fakeQuantizeShapes[3], 20.f, "outputHigh"), + 256ul); + fakeQuantize->set_friendly_name("fakeQuantize"); + + return fakeQuantize; +} +} // namespace + +std::shared_ptr FakeQuantizeFunction::get( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint) { + assert(4ul, fakeQuantizeShapes.size()); + + const auto parameter = std::make_shared(inputType, inputShape); + parameter->set_friendly_name("parameter"); + + const auto convert1 = std::make_shared(parameter, ov::element::u8); + convert1->set_friendly_name("convert1"); + + const auto relu1 = std::make_shared(convert1); + relu1->set_friendly_name("relu1"); + + const auto convert2 = std::make_shared(relu1, ov::element::f32); + convert2->set_friendly_name("convert2"); + + const auto slope2 = std::make_shared(ov::element::f32, ov::Shape{}, std::vector{-1.f}); + const auto relu2 = std::make_shared(convert2, slope2); + relu2->set_friendly_name("relu2"); + + const auto fakeQuantize = getFakeQuantize(relu2, inputShape, inputType, fakeQuantizeShapes, zeroPoint); + fakeQuantize->set_friendly_name("fakeQuantize"); + + const auto relu3 = std::make_shared(fakeQuantize); + relu3->set_friendly_name("relu3"); + + const auto result = std::make_shared(relu3); + result->set_friendly_name("result"); + + return std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{parameter}, "FakeQuantizeFunction"); +} + +std::shared_ptr FakeQuantizeFunction::getSubgraphWithFakeQuantize( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint) { + assert(4ul, fakeQuantizeShapes.size()); + + auto getSubgraphBody = []( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint) { + const auto parameter = std::make_shared(inputType, inputShape); + parameter->set_friendly_name("parameter"); + + const auto fakeQuantize = getFakeQuantize(parameter, inputShape, inputType, fakeQuantizeShapes, zeroPoint); + + const auto result = std::make_shared(fakeQuantize); + result->set_friendly_name("result"); + + return std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{parameter}, "SubgraphWithFakeQuantizeBody"); + }; + + const auto parameter = std::make_shared(inputType, inputShape); + parameter->set_friendly_name("parameter"); + + const auto subgraph = std::make_shared( + ngraph::OutputVector {parameter}, + getSubgraphBody(inputShape, inputType, fakeQuantizeShapes, zeroPoint)); + subgraph->set_friendly_name("subgraph"); + + const auto result = std::make_shared(subgraph); + result->set_friendly_name("result"); + + return std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{parameter}, "SubgraphWithFakeQuantize"); +} + +std::shared_ptr FakeQuantizeFunction::getSubgraphWithDecomposedFakeQuantize( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint) { + assert(fakeQuantizeShapes.size() == 4ul); + + auto getSubgraphBody = []( + const ngraph::Shape& inputShape, + const element::Type inputType, + const std::vector& fakeQuantizeShapes, + const float zeroPoint) { + const auto parameter = std::make_shared(inputType, inputShape); + parameter->set_friendly_name("parameter"); + + const auto maximum = std::make_shared( + parameter, + std::make_shared(element::f32, Shape{}, std::vector{1.f})); + maximum->set_friendly_name("inputLow"); + + const auto minimum = std::make_shared( + maximum, + std::make_shared(element::f32, Shape{}, std::vector{20.f})); + minimum->set_friendly_name("inputHigh"); + + const auto multiply = std::make_shared( + minimum, + std::make_shared(element::f32, Shape{}, std::vector{13.4211f})); + multiply->set_friendly_name("multiply"); + + const auto subtract = std::make_shared( + multiply, + std::make_shared(element::f32, Shape{}, std::vector{13.4211f})); + subtract->set_friendly_name("subtract"); + + const auto round = std::make_shared(subtract, ngraph::opset5::Round::RoundMode::HALF_TO_EVEN); + round->set_friendly_name("round"); + + const auto devide = std::make_shared( + round, + std::make_shared(element::f32, Shape{}, std::vector{0.0745098f})); + devide->set_friendly_name("devide"); + + const auto add = std::make_shared( + devide, + std::make_shared(element::f32, Shape{}, std::vector{1.f})); + add->set_friendly_name("add"); + + const auto result = std::make_shared(add); + result->set_friendly_name("result"); + + return std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{parameter}, "SubgraphWithDecomposedFakeQuantizeBody"); + }; + + const auto parameter = std::make_shared(inputType, inputShape); + parameter->set_friendly_name("parameter"); + + const auto subgraph = std::make_shared( + ngraph::OutputVector {parameter}, + getSubgraphBody(inputShape, inputType, fakeQuantizeShapes, zeroPoint)); + subgraph->set_friendly_name("subgraph"); + + const auto result = std::make_shared(subgraph); + result->set_friendly_name("result"); + + return std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{parameter}, "SubgraphWithDecomposedFakeQuantize"); +} + +} // namespace snippets +} // namespace test +} // namespace ov