diff --git a/inference-engine/src/gna_plugin/transformations/reorder_activation_and_pooling.cpp b/inference-engine/src/gna_plugin/transformations/reorder_activation_and_pooling.cpp index 7e67d900e38..141c53df542 100644 --- a/inference-engine/src/gna_plugin/transformations/reorder_activation_and_pooling.cpp +++ b/inference-engine/src/gna_plugin/transformations/reorder_activation_and_pooling.cpp @@ -9,7 +9,7 @@ #include #include #include - +#include #include using namespace GNAPluginNS; @@ -63,6 +63,7 @@ ReorderActivationAndPooling::ReorderActivationAndPooling() { } ngraph::replace_output_update_name(pool_node->output(0), pool_node->input_value(0)); + ngraph::copy_runtime_info(pool_node, new_pool); return true; }; diff --git a/inference-engine/tests/unit/gna/ngraph/transformations/gna_reorder_activation_and_pooling.cpp b/inference-engine/tests/unit/gna/ngraph/transformations/gna_reorder_activation_and_pooling.cpp new file mode 100644 index 00000000000..beb881eebde --- /dev/null +++ b/inference-engine/tests/unit/gna/ngraph/transformations/gna_reorder_activation_and_pooling.cpp @@ -0,0 +1,385 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "transformations/reorder_activation_and_pooling.hpp" + +#include "common_test_utils/ngraph_test_utils.hpp" +#include +#include +#include +#include + +namespace testing { + +namespace { + +class IActivationNodeFactory { +public: + virtual ~IActivationNodeFactory() = default; + virtual std::shared_ptr createNode(const ngraph::Output& in) = 0; +}; + +template +class ActivationNodeFactory : public IActivationNodeFactory { +public: + ActivationNodeFactory() = default; + std::shared_ptr createNode(const ngraph::Output& operation_before) override { + return std::make_shared(operation_before); + } +private: + ActivationNodeFactory(const ActivationNodeFactory&) = delete; + ActivationNodeFactory& operator=(const ActivationNodeFactory& ) = delete; +}; + +template <> +class ActivationNodeFactory : public IActivationNodeFactory { +public: + ActivationNodeFactory(const double min, const double max) : min_(min), max_(max) {} + std::shared_ptr createNode(const ngraph::Output& operation_before) override { + return std::make_shared(operation_before, min_, max_); + } +private: + ActivationNodeFactory(const ActivationNodeFactory&) = delete; + ActivationNodeFactory& operator=(const ActivationNodeFactory& ) = delete; +private: + const double min_; + const double max_; +}; + +using ActivationFactoryPtr = std::shared_ptr; + +template +ActivationFactoryPtr createActivationFactory(Args&& ... args) { + return std::make_shared>(std::forward(args) ...); +} + +// ---------------------------------------------------------------------------------------------------------------------- + +/* Variants: + Convolution -> Add -> Activation -> MaxPool + Convolution -> Activation -> MaxPool + */ + +typedef std::tuple< + ActivationFactoryPtr, // activation Node factory + bool // do we need to create ngraph::opset7::Add Node or not +> ConvolutionActivationPoolTestOptions; + +class ConvolutionActivationPoolTestFixture : public CommonTestUtils::TestsCommon, + public testing::WithParamInterface { +public: + void SetUp() override; + std::shared_ptr get_initial_function(ActivationFactoryPtr activation_factory, + bool isAddNodeNeeded); + std::shared_ptr get_reference(ActivationFactoryPtr activation_factory, + bool isAddNodeNeeded); +public: + std::shared_ptr function, reference_function; +}; + +void ConvolutionActivationPoolTestFixture::SetUp() { + ActivationFactoryPtr activation_factory; + bool isAddNodeNeeded = false; + std::tie(activation_factory, isAddNodeNeeded) = GetParam(); + + function = get_initial_function(activation_factory, isAddNodeNeeded); + reference_function = get_reference(activation_factory, isAddNodeNeeded); +} + +std::shared_ptr ConvolutionActivationPoolTestFixture::get_initial_function(ActivationFactoryPtr activation_factory, + bool isAddNodeNeeded) { + auto input_params_convolution = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + auto input_params_add = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto weights = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 3, 1, 1}, {1}); + auto bias = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 1, 1}, {1}); + auto convolution_operation = std::make_shared(input_params_convolution, + weights, + ngraph::Strides{1, 1}, + ngraph::CoordinateDiff{0, 0}, + ngraph::CoordinateDiff{0, 0}, + ngraph::Strides{1, 1}); + + std::shared_ptr last_operation = convolution_operation; + if (isAddNodeNeeded) { + auto add_operation = std::make_shared(convolution_operation, + input_params_add); + last_operation = add_operation; + } + auto activation = activation_factory->createNode(last_operation); + + auto max_pool_operation = std::make_shared(activation, + ngraph::Strides{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}); + + auto result = std::make_shared(max_pool_operation); + return std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{input_params_convolution, + input_params_add}); +} + +std::shared_ptr ConvolutionActivationPoolTestFixture::get_reference(ActivationFactoryPtr activation_factory, + bool isAddNodeNeeded) { + auto input_params_convolution = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto input_params_add = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto weights = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 3, 1, 1}, {1}); + auto bias = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 1, 1}, {1}); + auto convolution_operation = std::make_shared(input_params_convolution, + weights, + ngraph::Strides{1, 1}, + ngraph::CoordinateDiff{0, 0}, + ngraph::CoordinateDiff{0, 0}, + ngraph::Strides{1, 1}); + + std::shared_ptr last_operation = convolution_operation; + if (isAddNodeNeeded) { + auto add_operation = std::make_shared(convolution_operation, + input_params_convolution); + last_operation = add_operation; + } + + auto max_pool_operation = std::make_shared(last_operation, + ngraph::Strides{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}); + + auto activation = activation_factory->createNode(max_pool_operation); + + auto result = std::make_shared(activation); + return std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{input_params_convolution, + input_params_add}); +} + +void execute_test(std::shared_ptr function, std::shared_ptr reference_function) { + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(function); + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(function, reference_function); + ASSERT_TRUE(result.valid); +} + +TEST_P(ConvolutionActivationPoolTestFixture, CompareFunctions) { + execute_test(function, reference_function); +} + +const std::vector activationFactories = { + createActivationFactory(), + createActivationFactory(), + createActivationFactory(), + createActivationFactory(), + createActivationFactory(), + createActivationFactory(), + createActivationFactory(), + createActivationFactory(0.1, 0.2) +}; + +INSTANTIATE_TEST_SUITE_P(ConvolutionActivationPoolTestSuite, ConvolutionActivationPoolTestFixture, + ::testing::Combine(::testing::ValuesIn(activationFactories), + ::testing::ValuesIn(std::vector{true, false}))); + +//----------------------------------------------------------------------------------------------------------- + +// Variant Convolution -> FakeQuantize -> MaxPool : ConvFqMp + +TEST(TransformationTests, ReorderActivationAndPoolingTestConvFqMp) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params_convolution = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto weights = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 3, 1, 1}, {1}); + auto bias = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 1, 1}, {1}); + auto convolution_operation = std::make_shared(input_params_convolution, + weights, + ngraph::Strides{1, 1}, + ngraph::CoordinateDiff{0, 0}, + ngraph::CoordinateDiff{0, 0}, + ngraph::Strides{1, 1}); + + auto input_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {1}); + auto input_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {20}); + auto output_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {0}); + auto output_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {10}); + auto fake_quantize_op = std::make_shared(convolution_operation, input_low, + input_high, output_low, + output_high, 11); + + auto max_pool_operation = std::make_shared(fake_quantize_op, + ngraph::Strides{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}); + + auto result = std::make_shared(max_pool_operation); + func = std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{input_params_convolution}); + + ngraph::pass::Manager m; + m.register_pass(); + + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + { + auto input_params_convolution = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto weights = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 3, 1, 1}, {1}); + auto bias = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 1, 1}, {1}); + auto convolution_operation = std::make_shared(input_params_convolution, + weights, + ngraph::Strides{1, 1}, + ngraph::CoordinateDiff{0, 0}, + ngraph::CoordinateDiff{0, 0}, + ngraph::Strides{1, 1}); + + auto max_pool_operation = std::make_shared(convolution_operation, + ngraph::Strides{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}); + + auto input_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {1}); + auto input_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {20}); + auto output_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {0}); + auto output_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {10}); + auto fake_quantize_op = std::make_shared(max_pool_operation, input_low, + input_high, output_low, + output_high, 11); + + auto result = std::make_shared(fake_quantize_op); + reference_func = std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{input_params_convolution}); + } + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +// Variant Convolution -> Add -> FakeQuantize -> MaxPool : ConvAddFqMp + +TEST(TransformationTests, ReorderActivationAndPoolingTestConvAddFqMp) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params_convolution = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto input_params_add = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto weights = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 3, 1, 1}, {1}); + auto bias = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 1, 1}, {1}); + auto convolution_operation = std::make_shared(input_params_convolution, + weights, + ngraph::Strides{1, 1}, + ngraph::CoordinateDiff{0, 0}, + ngraph::CoordinateDiff{0, 0}, + ngraph::Strides{1, 1}); + + auto add_operation = std::make_shared(convolution_operation, + input_params_add); + + auto input_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {1}); + auto input_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {20}); + auto output_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {0}); + auto output_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {10}); + auto fake_quantize_op = std::make_shared(add_operation, input_low, + input_high, output_low, + output_high, 11); + + auto max_pool_operation = std::make_shared(fake_quantize_op, + ngraph::Strides{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}); + + auto result = std::make_shared(max_pool_operation); + func = std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{input_params_convolution, input_params_add}); + + ngraph::pass::Manager m; + m.register_pass(); + + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + { + auto input_params_convolution = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto input_params_add = std::make_shared(ngraph::element::f32, + ngraph::Shape{1, 3, 64, 64}); + + auto weights = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 3, 1, 1}, {1}); + auto bias = ngraph::opset7::Constant::create(ngraph::element::f32, + ngraph::Shape{3, 1, 1}, {1}); + auto convolution_operation = std::make_shared(input_params_convolution, + weights, + ngraph::Strides{1, 1}, + ngraph::CoordinateDiff{0, 0}, + ngraph::CoordinateDiff{0, 0}, + ngraph::Strides{1, 1}); + + auto add_operation = std::make_shared(convolution_operation, + input_params_add); + + auto max_pool_operation = std::make_shared(add_operation, + ngraph::Strides{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}, + ngraph::Shape{1, 1}); + + auto input_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {1}); + auto input_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {20}); + auto output_low = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {0}); + auto output_high = ngraph::opset7::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {10}); + auto fake_quantize_op = std::make_shared(max_pool_operation, input_low, + input_high, output_low, + output_high, 11); + + auto result = std::make_shared(fake_quantize_op); + reference_func = std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{input_params_convolution, input_params_add}); + } + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +} // namespace + +} // namespace testing