From 176c7e331ed90c054f93bc0dc576cf4396a547aa Mon Sep 17 00:00:00 2001 From: Aleksandr Voron Date: Tue, 28 Mar 2023 12:30:55 +0200 Subject: [PATCH] Adedd GroupConv transformations (#122) --- .../cpu_opset/arm/pass/convert_group_conv.cpp | 65 +++++++++++++++++ .../cpu_opset/arm/pass/convert_group_conv.hpp | 18 +++++ .../arm/pass/convert_group_conv1d.cpp | 73 +++++++++++++++++++ .../arm/pass/convert_group_conv1d.hpp | 29 ++++++++ .../transformation_pipeline.cpp | 5 ++ 5 files changed, 190 insertions(+) create mode 100644 src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.cpp create mode 100644 src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.hpp create mode 100644 src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.cpp create mode 100644 src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.hpp diff --git a/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.cpp b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.cpp new file mode 100644 index 00000000000000..d9270a324e4765 --- /dev/null +++ b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2020-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + + +#include "convert_group_conv.hpp" + +#include + +#include +#include +#include + +ov::intel_cpu::ConvertGroupConvolution::ConvertGroupConvolution() { + auto gconv = ngraph::pattern::wrap_type(); + + ngraph::matcher_pass_callback callback = [](ngraph::pattern::Matcher& m) { + enum Inputs {Data, Weights}; + auto gconv = std::dynamic_pointer_cast(m.get_match_root()); + if (!gconv) { + return false; + } + + auto data_shape = gconv->get_input_shape(Inputs::Data); + // Weights layout GOIYX + size_t groups = gconv->get_input_shape(Inputs::Weights)[0]; + if (groups == data_shape.at(1) && groups == gconv->get_output_shape(0)[1]) { // depthwise case + return false; + } + + ngraph::NodeVector replace_nodes; + auto split_weights = std::make_shared(gconv->input_value(Inputs::Weights), + ov::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}), + groups); + replace_nodes.push_back(split_weights); + + auto axis = ov::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto split = std::make_shared(gconv->input_value(Inputs::Data), axis, groups); + replace_nodes.push_back(split); + + ngraph::NodeVector concat_inputs; + for (size_t g = 0; g < groups; g++) { + auto out = split->output(g); + auto filter = std::make_shared(split_weights->output(g), + ov::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0})); + auto conv = std::make_shared(out, + filter, + gconv->get_strides(), + gconv->get_pads_begin(), + gconv->get_pads_end(), + gconv->get_dilations(), + gconv->get_auto_pad()); + concat_inputs.push_back(conv); + replace_nodes.push_back(conv); + } + auto concat = std::make_shared(concat_inputs, 1); + replace_nodes.push_back(concat); + + concat->set_friendly_name(gconv->get_friendly_name()); + ngraph::copy_runtime_info(gconv, replace_nodes); + ngraph::replace_node(gconv, concat); + return true; + }; + auto m = std::make_shared(gconv, "ConvertGroupConvolution"); + register_matcher(m, callback); +} diff --git a/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.hpp b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.hpp new file mode 100644 index 00000000000000..c26b4651af22f3 --- /dev/null +++ b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv.hpp @@ -0,0 +1,18 @@ +// Copyright (C) 2020-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +namespace ov { +namespace intel_cpu { + +class ConvertGroupConvolution: public ngraph::pass::MatcherPass { +public: + OPENVINO_RTTI("ConvertGroupConvolution", "0"); + ConvertGroupConvolution(); +}; +} // namespace intel_cpu +} // namespace ov diff --git a/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.cpp b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.cpp new file mode 100644 index 00000000000000..8b1632354d8aa7 --- /dev/null +++ b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2020-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + + +#include "convert_group_conv1d.hpp" + +#include + +#include +#include +#include +#include + +template +ngraph::matcher_pass_callback ov::intel_cpu::ConvertConv1DBase::convert_conv1d_to_conv2d() { + return [&](ngraph::pattern::Matcher& m) { + auto conv = std::dynamic_pointer_cast(m.get_match_root()); + if (!conv) { + return false; + } + + auto input_shape = conv->get_input_shape(0); + // is Conv1D + if (input_shape.size() != 3) { + return false; + } + + auto input = conv->input_value(0); + auto weights = conv->input_value(1); + auto input2d_shape = input_shape; + input2d_shape.push_back(1); + auto in2d_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{4}, input2d_shape); + + auto weights2d_shape = weights.get_shape(); + weights2d_shape.push_back(1); + auto w_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{weights2d_shape.size()}, weights2d_shape); + + auto input2d = std::make_shared(input, in2d_shape, true); + auto weights2d = std::make_shared(weights, w_shape, true); + + auto conv2d = std::make_shared(input2d, + weights2d, + ngraph::Strides{conv->get_strides()[0], 1}, + ngraph::CoordinateDiff{conv->get_pads_begin()[0], 0}, + ngraph::CoordinateDiff{conv->get_pads_end()[0], 0}, + ngraph::Strides{conv->get_dilations()[0], 1}, + conv->get_auto_pad()); + + auto in_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{3}, conv->get_output_shape(0)); + auto reshape = std::make_shared(conv2d, in_shape, true); + + reshape->set_friendly_name(conv->get_friendly_name()); + ngraph::copy_runtime_info(conv, {input2d, weights2d, conv2d, reshape}); + ngraph::replace_node(conv, reshape); + return true; + }; +} + +ov::intel_cpu::ConvertConv1D::ConvertConv1D() { + auto m = std::make_shared( + ngraph::pattern::wrap_type({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()), + ngraph::pattern::any_input(ngraph::pattern::has_static_shape())}, + ngraph::pattern::has_static_shape()), "ConvertConvolutionToArm"); + register_matcher(m, convert_conv1d_to_conv2d()); +} + +ov::intel_cpu::ConvertGroupConv1D::ConvertGroupConv1D() { + auto m = std::make_shared( + ngraph::pattern::wrap_type({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()), + ngraph::pattern::any_input(ngraph::pattern::has_static_shape())}, + ngraph::pattern::has_static_shape()), "ConvertGroupConvolutionToArm"); + register_matcher(m, convert_conv1d_to_conv2d()); +} \ No newline at end of file diff --git a/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.hpp b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.hpp new file mode 100644 index 00000000000000..c5f197e64f68a7 --- /dev/null +++ b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_group_conv1d.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2020-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +namespace ov { +namespace intel_cpu { +class ConvertConv1DBase: public ngraph::pass::MatcherPass { +protected: + OPENVINO_RTTI("ConvertConv1DBase", "0"); + template + ngraph::matcher_pass_callback convert_conv1d_to_conv2d(); +}; + +class ConvertConv1D: public ConvertConv1DBase { +public: + OPENVINO_RTTI("ConvertConv1D", "0"); + ConvertConv1D(); +}; + +class ConvertGroupConv1D: public ConvertConv1DBase { +public: + OPENVINO_RTTI("ConvertGroupConv1D", "0"); + ConvertGroupConv1D(); +}; +} // namespace intel_cpu +} // namespace ov \ No newline at end of file diff --git a/src/plugins/intel_cpu/src/transformations/transformation_pipeline.cpp b/src/plugins/intel_cpu/src/transformations/transformation_pipeline.cpp index f654f1462c1c1e..3ee532794782ca 100644 --- a/src/plugins/intel_cpu/src/transformations/transformation_pipeline.cpp +++ b/src/plugins/intel_cpu/src/transformations/transformation_pipeline.cpp @@ -93,6 +93,8 @@ #include "transformations/snippets/x64/pass/snippets_mark_skipped.hpp" #include "transformations/cpu_opset/x64/pass/mha_fusion.hpp" #include "transformations/cpu_opset/x64/pass/convert_to_interaction.hpp" +#include "transformations/cpu_opset/arm/pass/convert_group_conv.hpp" +#include "transformations/cpu_opset/arm/pass/convert_group_conv1d.hpp" #include "transformations/cpu_opset/arm/pass/convert_reduce_multi_axis.hpp" #include "transformations/cpu_opset/arm/pass/mish_decomposition.hpp" #include "transformations/cpu_opset/common/pass/convert_fq_rnn_to_quantized_rnn.hpp" @@ -253,6 +255,9 @@ void Transformations::PreLpt(const std::vector& defaultPrecis CPU_REGISTER_PASS_X64(manager, ConvertInteractionInt8); CPU_REGISTER_PASS_ARM(manager, ConvertReduceMultiAxis); CPU_REGISTER_PASS_ARM(manager, MishDecomposition); + CPU_REGISTER_PASS_ARM(manager, ConvertConv1D); + CPU_REGISTER_PASS_ARM(manager, ConvertGroupConv1D); + CPU_REGISTER_PASS_ARM(manager, ConvertGroupConvolution); // SpaceToDepth/ DepthToSpace node implementation supports only equal input/output tensors with rank <= 5 CPU_SET_CALLBACK_COMMON(manager,