diff --git a/src/bindings/python/src/openvino/offline_transformations/__init__.py b/src/bindings/python/src/openvino/offline_transformations/__init__.py index 1300aa45064..29a79625fcd 100644 --- a/src/bindings/python/src/openvino/offline_transformations/__init__.py +++ b/src/bindings/python/src/openvino/offline_transformations/__init__.py @@ -41,8 +41,8 @@ def apply_fused_names_cleanup(model): @deprecated(version="2023.1", message="The module is private and following namespace " "`offline_transformations` will be removed in " "the future.") -def apply_moc_transformations(model, cf): - _base.apply_moc_transformations(model, cf) +def apply_moc_transformations(model, cf, smart_reshape=False): + _base.apply_moc_transformations(model, cf, smart_reshape) @deprecated(version="2023.1", message="The module is private and following namespace " "`offline_transformations` will be removed in " "the future.") diff --git a/src/bindings/python/src/pyopenvino/core/offline_transformations.cpp b/src/bindings/python/src/pyopenvino/core/offline_transformations.cpp index 68d2c461c22..a4dbe29affe 100644 --- a/src/bindings/python/src/pyopenvino/core/offline_transformations.cpp +++ b/src/bindings/python/src/pyopenvino/core/offline_transformations.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "openvino/pass/low_latency.hpp" #include "openvino/pass/manager.hpp" @@ -33,13 +34,16 @@ void regmodule_offline_transformations(py::module m) { m_offline_transformations.def( "apply_moc_transformations", - [](std::shared_ptr model, bool cf) { + [](std::shared_ptr model, bool cf, bool smart_reshape) { ov::pass::Manager manager; + if (smart_reshape) + manager.register_pass(); manager.register_pass(cf); manager.run_passes(model); }, py::arg("model"), - py::arg("cf")); + py::arg("cf"), + py::arg("smart_reshape") = false); m_offline_transformations.def( "apply_moc_legacy_transformations", diff --git a/src/bindings/python/tests/test_transformations/test_offline_api.py b/src/bindings/python/tests/test_transformations/test_offline_api.py index 01d440496b6..462849f7820 100644 --- a/src/bindings/python/tests/test_transformations/test_offline_api.py +++ b/src/bindings/python/tests/test_transformations/test_offline_api.py @@ -104,6 +104,15 @@ def test_moc_transformations(): assert len(model.get_ops()) == 3 +def test_moc_with_smart_reshape(): + model = get_test_model() + + apply_moc_transformations(model, cf=False, smart_reshape=True) + + assert model is not None + assert len(model.get_ops()) == 3 + + def test_pot_transformations(): model = get_test_model() diff --git a/src/common/transformations/include/transformations/smart_reshape/shape_of_const_folding.hpp b/src/common/transformations/include/transformations/smart_reshape/shape_of_const_folding.hpp new file mode 100644 index 00000000000..462f14dc6ec --- /dev/null +++ b/src/common/transformations/include/transformations/smart_reshape/shape_of_const_folding.hpp @@ -0,0 +1,25 @@ +// Copyright (C) 2018-2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include "openvino/pass/graph_rewrite.hpp" + +namespace ov { +namespace pass { + +/** + * @ingroup ie_transformation_common_api + * @brief ShapeOfConstFolding constantfolds ShapeOf->Constant subgraph + */ +class TRANSFORMATIONS_API ShapeOfConstFolding : public MatcherPass { +public: + OPENVINO_RTTI("ShapeOfConstFolding", "0"); + ShapeOfConstFolding(); +}; + +} // namespace pass +} // namespace ov diff --git a/src/common/transformations/src/transformations/smart_reshape/shape_of_const_folding.cpp b/src/common/transformations/src/transformations/smart_reshape/shape_of_const_folding.cpp new file mode 100644 index 00000000000..0ff1f214c27 --- /dev/null +++ b/src/common/transformations/src/transformations/smart_reshape/shape_of_const_folding.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2018-2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/smart_reshape/shape_of_const_folding.hpp" + +#include "itt.hpp" +#include "openvino/core/validation_util.hpp" +#include "openvino/op/shape_of.hpp" +#include "openvino/opsets/opset10.hpp" +#include "openvino/pass/pattern/op/wrap_type.hpp" + +ov::pass::ShapeOfConstFolding::ShapeOfConstFolding() { + MATCHER_SCOPE(ShapeOfConstFolding); + auto constant_label = pattern::wrap_type(); + auto shape_of_label = pattern::wrap_type({constant_label}); + + matcher_pass_callback callback = [=](pattern::Matcher& m) -> bool { + auto node = m.get_match_root(); + if (auto constant = get_constant_from_source(node)) { + constant->set_friendly_name(node->get_friendly_name()); + replace_node(node, constant); + return true; + } + + return false; + }; + + auto m = std::make_shared(shape_of_label, matcher_name); + register_matcher(m, callback); +} diff --git a/src/common/transformations/src/transformations/smart_reshape/smart_reshape.cpp b/src/common/transformations/src/transformations/smart_reshape/smart_reshape.cpp index c27462b59df..05b352b275f 100644 --- a/src/common/transformations/src/transformations/smart_reshape/smart_reshape.cpp +++ b/src/common/transformations/src/transformations/smart_reshape/smart_reshape.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,8 @@ bool ngraph::pass::SmartReshape::run_on_model(const std::shared_ptr(); dynamic_manager.register_pass(); + dynamic_manager.register_pass(); dynamic_manager.run_passes(f); + return true; } diff --git a/src/tests/functional/inference_engine/transformations/smart_reshape/shape_of_const_folding.cpp b/src/tests/functional/inference_engine/transformations/smart_reshape/shape_of_const_folding.cpp new file mode 100644 index 00000000000..e345faf4c92 --- /dev/null +++ b/src/tests/functional/inference_engine/transformations/smart_reshape/shape_of_const_folding.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2018-2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "common_test_utils/ngraph_test_utils.hpp" +#include "openvino/op/shape_of.hpp" +#include "openvino/opsets/opset10.hpp" +#include "transformations/smart_reshape/shape_of_const_folding.hpp" + + +using namespace ov; + +TEST_F(TransformationTestsF, ShapeOfConstFolding) { + { + auto input = std::make_shared(element::f32, Shape{10, 20}, 1); + auto shape_of = std::make_shared(input); + model = std::make_shared(shape_of, ParameterVector{}); + } + + manager.register_pass(); + + { + auto input = std::make_shared(element::i64, Shape{2}, std::vector{10, 20}); + model_ref = std::make_shared(input, ParameterVector{}); + } +} + +TEST_F(TransformationTestsF, v0ShapeOfConstFolding) { + { + auto input = std::make_shared(element::f32, Shape{10, 20}, 1); + auto shape_of = std::make_shared(input); + model = std::make_shared(shape_of, ParameterVector{}); + } + + manager.register_pass(); + + { + auto input = std::make_shared(element::i64, Shape{2}, std::vector{10, 20}); + model_ref = std::make_shared(input, ParameterVector{}); + } +} + +TEST_F(TransformationTestsF, ShapeOfConstFoldingNegative) { + { + auto input = std::make_shared(element::f32, Shape{10, 20}); + auto shape_of = std::make_shared(input); + model = std::make_shared(shape_of, ParameterVector{input}); + } + + manager.register_pass(); +} diff --git a/tools/mo/openvino/tools/mo/back/offline_transformations.py b/tools/mo/openvino/tools/mo/back/offline_transformations.py index 5478277662a..30b0e335295 100644 --- a/tools/mo/openvino/tools/mo/back/offline_transformations.py +++ b/tools/mo/openvino/tools/mo/back/offline_transformations.py @@ -36,7 +36,7 @@ def apply_user_transformations(func: object, transforms: list): def apply_moc_transformations(func: object): from openvino._offline_transformations import apply_moc_transformations # pylint: disable=import-error,no-name-in-module - apply_moc_transformations(func, False) + apply_moc_transformations(func, cf=False, smart_reshape=True) def apply_moc_legacy_transformations(func: object, params_with_custom_types: List[str]): diff --git a/tools/mo/openvino/tools/mo/ops/strided_slice.py b/tools/mo/openvino/tools/mo/ops/strided_slice.py index c6e52d58cb5..3e617be92b8 100644 --- a/tools/mo/openvino/tools/mo/ops/strided_slice.py +++ b/tools/mo/openvino/tools/mo/ops/strided_slice.py @@ -44,8 +44,6 @@ class StridedSlice(Op): @staticmethod def infer(node: Node): - StridedSlice.align_mask_with_slice_rank(node, node.in_port(1).data.get_shape()[0]) - data_shape = node.in_port(0).data.get_shape() data_value = node.in_port(0).data.get_value() slices = StridedSlice.get_slices(node, data_shape) @@ -77,9 +75,9 @@ class StridedSlice(Op): slices = [[]] * slice_rank in_idx = 0 # index along input tensor shapes, note that input_rank not necessary is equal to slice_rank for i in range(slice_rank): - if node.new_axis_mask[i]: + if i < len(node.new_axis_mask) and node.new_axis_mask[i]: slices[i] = np.newaxis - elif node.shrink_axis_mask[i]: + elif i < len(node.shrink_axis_mask) and node.shrink_axis_mask[i]: if begin is not None and begin[i] is not dynamic_dimension: slices[i] = int(begin[i]) # the normalization is needed for the ConvertGroupedStridedSlice transformation @@ -87,20 +85,20 @@ class StridedSlice(Op): slices[i] += int(data_shape[in_idx]) else: slices[i] = dynamic_dimension_value - elif node.ellipsis_mask[i]: + elif i < len(node.ellipsis_mask) and node.ellipsis_mask[i]: slices[i] = ... in_idx += input_rank - slice_rank + np.count_nonzero(node.new_axis_mask) else: if begin is not None and end is not None and strides is not None: start, stop = begin[i], end[i] - if not node.begin_mask[i]: # if begin, and end are not specified take the whole range + if i < len(node.begin_mask) and not node.begin_mask[i]: # if begin, and end are not specified take the whole range start = None - if not node.end_mask[i]: + if i < len(node.end_mask) and not node.end_mask[i]: stop = None slices[i] = slice(start, stop, strides[i]) else: slices[i] = dynamic_dimension_value - in_idx += 1 if not node.new_axis_mask[i] else 0 + in_idx += 1 if i < len(node.new_axis_mask) and not node.new_axis_mask[i] else 0 return slices @staticmethod diff --git a/tools/mo/openvino/tools/mo/utils/ir_reader/extenders/strided_slice_extender.py b/tools/mo/openvino/tools/mo/utils/ir_reader/extenders/strided_slice_extender.py index b7d465e41ee..3929f123682 100644 --- a/tools/mo/openvino/tools/mo/utils/ir_reader/extenders/strided_slice_extender.py +++ b/tools/mo/openvino/tools/mo/utils/ir_reader/extenders/strided_slice_extender.py @@ -20,7 +20,7 @@ class StridedSlice_extender(Extender): else: assert attr not in ['begin_mask', 'end_mask'],\ '{} is not defined for the node {}'.format(attr, op.soft_get('name', op.id)) - op[attr] = int64_array([0]) + op[attr] = int64_array([]) op.begin_mask = int64_array([1 - i for i in op.begin_mask]) op.end_mask = int64_array([1 - i for i in op.end_mask])