diff --git a/src/common/transformations/include/transformations/common_optimizations/adaptive_pool_to_reduce.hpp b/src/common/transformations/include/transformations/common_optimizations/adaptive_pool_to_reduce.hpp new file mode 100644 index 00000000000000..84ff14d4bd36ce --- /dev/null +++ b/src/common/transformations/include/transformations/common_optimizations/adaptive_pool_to_reduce.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +namespace ov { +namespace pass { + +class TRANSFORMATIONS_API AdaptivePoolToReduce; + +} // namespace pass +} // namespace ov + +/** + * @ingroup ie_transformation_common_api + * @brief AdaptivePoolToReduce transformation replaces AdaptiveXXXPool with ReduceXXX when possible + */ + +class ov::pass::AdaptivePoolToReduce : public ov::pass::MatcherPass { +public: + OPENVINO_RTTI("AdaptivePoolToReduce", "0"); + AdaptivePoolToReduce(); +}; diff --git a/src/common/transformations/src/transformations/common_optimizations/adaptive_pool_to_reduce.cpp b/src/common/transformations/src/transformations/common_optimizations/adaptive_pool_to_reduce.cpp new file mode 100644 index 00000000000000..6374206435e7b9 --- /dev/null +++ b/src/common/transformations/src/transformations/common_optimizations/adaptive_pool_to_reduce.cpp @@ -0,0 +1,63 @@ +// Copyright (C) 2018-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/adaptive_pool_to_reduce.hpp" + +#include +#include + +#include "itt.hpp" +#include "openvino/core/rt_info.hpp" +#include "openvino/op/adaptive_avg_pool.hpp" +#include "openvino/op/adaptive_max_pool.hpp" +#include "openvino/op/constant.hpp" +#include "openvino/op/reduce_max.hpp" +#include "openvino/op/reduce_mean.hpp" +#include "openvino/pass/pattern/op/wrap_type.hpp" +#include "transformations/utils/utils.hpp" + +using namespace ov::op; + +ov::pass::AdaptivePoolToReduce::AdaptivePoolToReduce() { + MATCHER_SCOPE(AdaptivePoolToReduce); + auto data_pattern = pattern::any_input(); + auto out_spatial_shape = pattern::wrap_type(); + auto a_pool = pattern::wrap_type({data_pattern, out_spatial_shape}); + + ov::matcher_pass_callback callback = [=](pattern::Matcher& m) { + const auto& pattern_map = m.get_pattern_map(); + + const auto& spatial_shape_c = std::dynamic_pointer_cast(pattern_map.at(out_spatial_shape)); + auto spatial_shape = spatial_shape_c->cast_vector(); + // Verify that all dimensions in adaptive pool shape are 1 + for (auto& s : spatial_shape) { + if (s != 1) + return false; + } + + auto axes = std::vector(spatial_shape.size(), 0); + std::iota(axes.begin(), axes.end(), 2); + auto axes_const = v0::Constant::create(element::i64, {spatial_shape.size()}, axes); + const auto adaptive_pool = pattern_map.at(a_pool); + std::shared_ptr res_node; + if (std::dynamic_pointer_cast(adaptive_pool)) { + res_node = std::make_shared(adaptive_pool->input_value(0), axes_const, true); + } else if (std::dynamic_pointer_cast(adaptive_pool)) { + if (adaptive_pool->outputs().size() > 1 && adaptive_pool->output(1).get_target_inputs().size() != 0) { + // If indexes are used we can't replace it + return false; + } + res_node = std::make_shared(adaptive_pool->input_value(0), axes_const, true); + } else { + return false; + } + adaptive_pool->output(0).replace(res_node); + res_node->set_friendly_name(adaptive_pool->get_friendly_name()); + copy_runtime_info(adaptive_pool, res_node); + return true; + }; + + auto m = std::make_shared(a_pool, matcher_name); + this->register_matcher(m, callback); +} diff --git a/src/common/transformations/src/transformations/common_optimizations/moc_transformations.cpp b/src/common/transformations/src/transformations/common_optimizations/moc_transformations.cpp index 581e7e76b56a70..a8ac682a490c10 100644 --- a/src/common/transformations/src/transformations/common_optimizations/moc_transformations.cpp +++ b/src/common/transformations/src/transformations/common_optimizations/moc_transformations.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -205,6 +206,7 @@ bool ov::pass::MOCTransformations::run_on_model(const std::shared_ptrset_name("ov::pass::CommonFusions"); REGISTER_PASS(manager, BinarizeWeights) diff --git a/src/common/transformations/tests/common_optimizations/adaptive_pool_to_reduce.cpp b/src/common/transformations/tests/common_optimizations/adaptive_pool_to_reduce.cpp new file mode 100644 index 00000000000000..dc94a3b054636e --- /dev/null +++ b/src/common/transformations/tests/common_optimizations/adaptive_pool_to_reduce.cpp @@ -0,0 +1,98 @@ +// Copyright (C) 2018-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; +using namespace ov; + +TEST_F(TransformationTestsF, AdaptiveAvgPool2dToReduceMean) { + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14}); + auto out_spatial_shape = opset10::Constant::create(element::i32, Shape{2}, {1, 1}); + auto adaptive_pool = std::make_shared(data, out_spatial_shape); + auto result = std::make_shared(adaptive_pool); + model = std::make_shared(ResultVector{result}, ParameterVector{data}); + manager.register_pass(); + } + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14}); + auto axes = opset10::Constant::create(element::i64, Shape{2}, {2, 3}); + auto reduce_mean = std::make_shared(data, axes, true); + auto result = std::make_shared(reduce_mean); + model_ref = std::make_shared(ResultVector{result}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, AdaptiveMaxPool2dToReduceMax) { + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14}); + auto out_spatial_shape = opset10::Constant::create(element::i32, Shape{2}, {1, 1}); + auto adaptive_pool = std::make_shared(data, out_spatial_shape); + auto result = std::make_shared(adaptive_pool); + model = std::make_shared(ResultVector{result}, ParameterVector{data}); + manager.register_pass(); + } + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14}); + auto axes = opset10::Constant::create(element::i64, Shape{2}, {2, 3}); + auto reduce_mean = std::make_shared(data, axes, true); + auto result = std::make_shared(reduce_mean); + model_ref = std::make_shared(ResultVector{result}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, AdaptiveMaxPool2dToReduceMaxUsedIndexes) { + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14}); + auto out_spatial_shape = opset10::Constant::create(element::i32, Shape{2}, {1, 1}); + auto adaptive_pool = std::make_shared(data, out_spatial_shape); + auto result1 = std::make_shared(adaptive_pool->output(0)); + auto result2 = std::make_shared(adaptive_pool->output(1)); + model = std::make_shared(ResultVector{result1, result2}, ParameterVector{data}); + manager.register_pass(); + } + // Reference model equals initial model +} + +TEST_F(TransformationTestsF, AdaptiveAvgPool3dToReduceMean) { + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14, 14}); + auto out_spatial_shape = opset10::Constant::create(element::i32, Shape{3}, {1, 1, 1}); + auto adaptive_pool = std::make_shared(data, out_spatial_shape); + auto result = std::make_shared(adaptive_pool); + model = std::make_shared(ResultVector{result}, ParameterVector{data}); + manager.register_pass(); + } + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14, 14}); + auto axes = opset10::Constant::create(element::i64, Shape{3}, {2, 3, 4}); + auto reduce_mean = std::make_shared(data, axes, true); + auto result = std::make_shared(reduce_mean); + model_ref = std::make_shared(ResultVector{result}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, AdaptiveMaxPool3dToReduceMax) { + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14, 14}); + auto out_spatial_shape = opset10::Constant::create(element::i32, Shape{3}, {1, 1, 1}); + auto adaptive_pool = std::make_shared(data, out_spatial_shape); + auto result = std::make_shared(adaptive_pool); + model = std::make_shared(ResultVector{result}, ParameterVector{data}); + manager.register_pass(); + } + { + auto data = std::make_shared(element::f32, PartialShape{1, 3, 14, 14, 14}); + auto axes = opset10::Constant::create(element::i64, Shape{3}, {2, 3, 4}); + auto reduce_mean = std::make_shared(data, axes, true); + auto result = std::make_shared(reduce_mean); + model_ref = std::make_shared(ResultVector{result}, ParameterVector{data}); + } +} diff --git a/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp b/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp index 64abf83c77f42f..2ac0567c07263f 100644 --- a/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp +++ b/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp @@ -170,7 +170,9 @@ std::vector disabledTestPatterns() { // 98151. Not valid sorting for slices in reference. R"(.*UniqueLayerTestCPU.*axis.*True.*)", // AUTO does not support import / export - R"(.*smoke_Auto_BehaviorTests/OVCompiledGraphImportExportTest.*(mportExport|readFromV10IR).*/targetDevice=(AUTO).*)" + R"(.*smoke_Auto_BehaviorTests/OVCompiledGraphImportExportTest.*(mportExport|readFromV10IR).*/targetDevice=(AUTO).*)", + // AdaptiveAvgPool is converted into Reduce op for suitable parameters. CPU Reduce impl doesn't support non planar layout for 3D case + R"(.*StaticAdaPoolAvg3DLayoutTest.*OS=\(1\).*_inFmts=(nwc|nCw16c|nCw8c).*)" }; #if defined(OPENVINO_ARCH_X86)