diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp index c69e402fc18..03fd8feed6d 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp @@ -59,17 +59,19 @@ ngraph::pass::ConvertGroupConvolution::ConvertGroupConvolution() { // Merge weights layout GOIYX to (G*O)IYX auto shape = gconv->input_value(1).get_shape(); - std::vector reshape_shape{static_cast(shape[0] * shape[1])}; + Shape reshape_shape{static_cast(shape[0] * shape[1])}; for (size_t i = 2; i < shape.size(); ++i) { reshape_shape.push_back(shape[i]); } Output weights; auto w_input = gconv->input_value(1).get_node_shared_ptr(); - if (std::dynamic_pointer_cast(w_input) && w_input->input_value(0).get_shape().size() == w_input->get_output_shape(0).size() - 1) { + if (std::dynamic_pointer_cast(w_input) && w_input->input_value(0).get_shape() == reshape_shape) { weights = w_input->input_value(0); } else { weights = std::make_shared(gconv->input_value(1), op::Constant::create(element::i64, Shape{reshape_shape.size()}, reshape_shape), true); + // FIXME: 42956 + // ngraph::copy_runtime_info(gconv, weights.get_node_shared_ptr()); } auto conv_ie = std::make_shared(gconv->input_value(0), weights, diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp index 9f673379d06..ccf1098701a 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp @@ -20,18 +20,21 @@ #include #include #include +#include #include "common_test_utils/ngraph_test_utils.hpp" using namespace testing; +using namespace ngraph; +using namespace ngraph::opset1; -using InputShape = ngraph::PartialShape; -using WeightsShape = ngraph::Shape; +using InputShape = PartialShape; +using WeightsShape = PartialShape; class ConvertConvolutionTest: public CommonTestUtils::TestsCommon, - public testing::WithParamInterface > { + public testing::WithParamInterface > { public: - std::shared_ptr f, f_ref; + std::shared_ptr f, f_ref; void SetUp() override { const auto& input_shape = std::get<0>(GetParam()); @@ -42,33 +45,35 @@ public: } private: - std::shared_ptr get_initial_function(const ngraph::PartialShape & input_shape, - const ngraph::Shape & weights_shape) { + std::shared_ptr get_initial_function(const PartialShape & input_shape, + const PartialShape & weights_shape) { + assert(weights_shape.is_static()); auto spatial_dims = input_shape.rank().get_length() - 2; - auto input = std::make_shared(ngraph::element::f32, input_shape); - auto weights = ngraph::opset1::Constant::create(ngraph::element::f32, weights_shape, {1}); - auto conv = std::make_shared(input, weights, ngraph::Strides(spatial_dims, 1), - ngraph::CoordinateDiff(spatial_dims, 0), ngraph::CoordinateDiff(spatial_dims, 0), ngraph::Strides(spatial_dims, 1)); + auto input = std::make_shared(element::f32, input_shape); + auto weights = Constant::create(element::f32, weights_shape.to_shape(), {1}); + auto conv = std::make_shared(input, weights, Strides(spatial_dims, 1), + CoordinateDiff(spatial_dims, 0), CoordinateDiff(spatial_dims, 0), Strides(spatial_dims, 1)); - return std::make_shared(ngraph::NodeVector{conv}, ngraph::ParameterVector{input}); + return std::make_shared(NodeVector{conv}, ParameterVector{input}); } - std::shared_ptr get_reference_function(const ngraph::PartialShape & input_shape, - const ngraph::Shape & weights_shape) { + std::shared_ptr get_reference_function(const PartialShape & input_shape, + const PartialShape & weights_shape) { + assert(weights_shape.is_static()); auto spatial_dims = input_shape.rank().get_length() - 2; - auto input = std::make_shared(ngraph::element::f32, input_shape); - auto weights = ngraph::opset1::Constant::create(ngraph::element::f32, weights_shape, {1}); - auto conv = std::make_shared(input, weights, ngraph::Strides(spatial_dims, 1), ngraph::Strides(spatial_dims, 1), - ngraph::CoordinateDiff(spatial_dims, 0), ngraph::CoordinateDiff(spatial_dims, 0), ngraph::element::f32); + auto input = std::make_shared(element::f32, input_shape); + auto weights = Constant::create(element::f32, weights_shape.get_shape(), {1}); + auto conv = std::make_shared(input, weights, Strides(spatial_dims, 1), Strides(spatial_dims, 1), + CoordinateDiff(spatial_dims, 0), CoordinateDiff(spatial_dims, 0), element::f32); - return std::make_shared(ngraph::NodeVector{conv}, ngraph::ParameterVector{input}); + return std::make_shared(NodeVector{conv}, ParameterVector{input}); } }; TEST_P(ConvertConvolutionTest, CompareFunctions) { const auto & orig_shape = f->get_output_partial_shape(0); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::ConvertConvolutions().run_on_function(f); + pass::InitNodeInfo().run_on_function(f); + pass::ConvertConvolutions().run_on_function(f); ASSERT_NO_THROW(check_rt_info(f)); auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; @@ -92,3 +97,86 @@ INSTANTIATE_TEST_CASE_P(ConvertConvolution, ConvertConvolutionTest, std::make_tuple(InputShape{DYN, 3, 10}, WeightsShape{3, 3, 1}), std::make_tuple(InputShape{2, DYN, 9}, WeightsShape{2, 3, 2}), std::make_tuple(InputShape{3, 3, DYN}, WeightsShape{1, 3, 3}))); + +TEST(ConvertConvolutionTest, GroupConvolutionWithReshape) { + PartialShape input_shape{1, 6, 64, 64}; + PartialShape weights_shape_before{2 * 3, 3, 5, 5}; + PartialShape weights_shape_after{2, 3, 3, 5, 5}; + size_t group = 2; + + std::shared_ptr f, f_ref; + { + auto spatial_dims = input_shape.rank().get_length() - 2; + auto input = std::make_shared(element::f32, input_shape); + auto weights = std::make_shared(element::f32, weights_shape_before); + auto reshape = std::make_shared(weights, Constant::create(element::i64, + Shape{static_cast(weights_shape_after.rank().get_length())}, weights_shape_after.to_shape()), true); + auto conv = std::make_shared(input, reshape, Strides(spatial_dims, 1), + CoordinateDiff(spatial_dims, 0), CoordinateDiff(spatial_dims, 0), Strides(spatial_dims, 1)); + + f = std::make_shared(NodeVector{conv}, ParameterVector{input, weights}); + } + + { + auto spatial_dims = input_shape.rank().get_length() - 2; + auto input = std::make_shared(element::f32, input_shape); + auto weights = std::make_shared(element::f32, weights_shape_before); + auto conv = std::make_shared(input, weights, Strides(spatial_dims, 1), Strides(spatial_dims, 1), + CoordinateDiff(spatial_dims, 0), CoordinateDiff(spatial_dims, 0), element::f32, group); + + f_ref = std::make_shared(NodeVector{conv}, ParameterVector{input, weights}); + } + + pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + auto res = compare_functions(f, f_ref); + ASSERT_TRUE(res.first) << res.second; +} + + +TEST(ConvertConvolutionTest, GroupConvolutionWithReshapeNeg) { + PartialShape input_shape{1, 6, 64, 64}; + PartialShape weights_shape_before{3, 2, 3, 5, 5}; + PartialShape weights_shape_after{2, 3, 3, 5, 5}; + PartialShape weights_shape_ref{2 * 3, 3, 5, 5}; + size_t group = 2; + + std::shared_ptr f, f_ref; + { + auto spatial_dims = input_shape.rank().get_length() - 2; + auto input = std::make_shared(element::f32, input_shape); + auto weights = std::make_shared(element::f32, weights_shape_before); + auto reshape = std::make_shared(weights, Constant::create(element::i64, + Shape{static_cast(weights_shape_after.rank().get_length())}, weights_shape_after.to_shape()), true); + auto conv = std::make_shared(input, reshape, Strides(spatial_dims, 1), + CoordinateDiff(spatial_dims, 0), CoordinateDiff(spatial_dims, 0), Strides(spatial_dims, 1)); + + f = std::make_shared(NodeVector{conv}, ParameterVector{input, weights}); + } + + { + auto spatial_dims = input_shape.rank().get_length() - 2; + auto input = std::make_shared(element::f32, input_shape); + auto weights_param = std::make_shared(element::f32, weights_shape_before); + auto reshape = std::make_shared(weights_param, Constant::create(element::i64, + Shape{static_cast(weights_shape_after.rank().get_length())}, weights_shape_after.to_shape()), true); + auto weights = std::make_shared(reshape, Constant::create(element::i64, + Shape{static_cast(weights_shape_ref.rank().get_length())}, weights_shape_ref.to_shape()), true); + auto conv = std::make_shared(input, weights, Strides(spatial_dims, 1), Strides(spatial_dims, 1), + CoordinateDiff(spatial_dims, 0), CoordinateDiff(spatial_dims, 0), element::f32, group); + + f_ref = std::make_shared(NodeVector{conv}, ParameterVector{input, weights_param}); + } + + pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + // FIXME: 42956 + // ASSERT_NO_THROW(check_rt_info(f)); + auto res = compare_functions(f, f_ref); + ASSERT_TRUE(res.first) << res.second; +} \ No newline at end of file