Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CPU][ARM] Dynamic shapes support in ARM transformations #17548

Merged
merged 14 commits into from
Jun 12, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,20 @@ ov::intel_cpu::ConvertGroupConvolution::ConvertGroupConvolution() {
if (!gconv) {
return false;
}

auto data_shape = gconv->get_input_shape(Inputs::Data);
const unsigned int channel_axis = 1;
const auto& input0 = gconv->input_value(0);
const auto& output_shape = gconv->get_output_partial_shape(0);
const auto& data_shape = input0.get_partial_shape();
// 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
int64_t groups = gconv->get_input_shape(Inputs::Weights)[0];

if (data_shape[channel_axis].is_dynamic() ||
output_shape[channel_axis].is_dynamic()) {
return false;
}

if (groups == data_shape[channel_axis].get_length() &&
groups == output_shape[channel_axis].get_length()) { // depthwise case
return false;
}

Expand All @@ -33,12 +42,12 @@ ov::intel_cpu::ConvertGroupConvolution::ConvertGroupConvolution() {
groups);
replace_nodes.push_back(split_weights);

auto axis = ov::opset8::Constant::create<int64_t>(ngraph::element::i64, ngraph::Shape{}, {1});
auto axis = ov::opset8::Constant::create<int64_t>(ngraph::element::i64, ngraph::Shape{}, {channel_axis});
auto split = std::make_shared<ov::opset1::Split>(gconv->input_value(Inputs::Data), axis, groups);
replace_nodes.push_back(split);

ngraph::NodeVector concat_inputs;
for (size_t g = 0; g < groups; g++) {
for (int64_t g = 0; g < groups; g++) {
auto out = split->output(g);
auto filter = std::make_shared<ov::opset1::Squeeze>(split_weights->output(g),
ov::opset8::Constant::create<int64_t>(ngraph::element::i64, ngraph::Shape{}, {0}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,56 @@
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/pass/graph_rewrite.hpp>

/*
* Description:
* ConvertGroupConvolution detects GroupConvolution and replaces it
* with a set of Convolution operations. Number of Convolution operations
* equals to number of groups.
*
* Before:
*
* +--------------+ +---------------+
* | Input tensor | | Kernel tensor |
* +-----------+--+ +-+-------------+
* | |
* +----v---------v----+
* | Group Convolution |
* +---------+---------+
* |
* +------v------+
* | Result |
* +-------------+
*
* After:
*
* +--------------+ +--------------+ +---------------+ +--------------+
* | Input tensor | | Constant (1) | | Kernel tensor | | Constant (0) |
* +-----------+--+ +-+------------+ +-----------+---+ +-+------------+
* | | | |
* +-v---------v-+ +-v---------v-+
* | Split | | Split |
* +-+-----------+--------+ +-+---------+-+
* | | | |
* | | +-----------v--+ +-v------------+
* | | | Squeeze | | Squeeze |
* | +----------+---+--------------+ +-+------------+
* | | | |
* | | +---------------+ |
* | | | |
* +-----------v---------v------------+ +-----------v---------v------------+
* | Convolution | | Convolution |
* +-----------------------------+----+ +---+------------------------------+
* | |
* +-----v----------v------+
* | Concat |
* +----------+------------+
* |
* +----------v------------+
* | Result |
* +-----------------------+
*
*/

namespace ov {
namespace intel_cpu {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,28 @@ ngraph::matcher_pass_callback ov::intel_cpu::ConvertConv1DBase::convert_conv1d_t
return false;
}

auto input_shape = conv->get_input_shape(0);
const auto& input0 = conv->input_value(0);
const auto& input_shape = input0.get_partial_shape();
// 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<ov::opset8::Constant>(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<ov::opset8::Constant>(ngraph::element::i64, ngraph::Shape{weights2d_shape.size()}, weights2d_shape);

auto input2d = std::make_shared<ov::opset8::Reshape>(input, in2d_shape, true);
auto weights2d = std::make_shared<ov::opset8::Reshape>(weights, w_shape, true);
auto getUnsqueeze = [&](const ngraph::Output<ngraph::Node>& node) {
auto rank = node.get_partial_shape().rank().get_length();
return std::make_shared<ov::opset8::Unsqueeze>(node,
ov::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {rank}));
};

auto input2d = getUnsqueeze(input);
auto weights2d = getUnsqueeze(weights);

auto conv2d = std::make_shared<Conv>(input2d,
weights2d,
Expand All @@ -46,8 +50,9 @@ ngraph::matcher_pass_callback ov::intel_cpu::ConvertConv1DBase::convert_conv1d_t
ngraph::Strides{conv->get_dilations()[0], 1},
conv->get_auto_pad());

auto in_shape = std::make_shared<ov::opset8::Constant>(ngraph::element::i64, ngraph::Shape{3}, conv->get_output_shape(0));
auto reshape = std::make_shared<ov::opset8::Reshape>(conv2d, in_shape, true);
auto reshape = std::make_shared<ov::opset8::Squeeze>(
conv2d,
ov::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {input_shape.rank().get_length()}));

reshape->set_friendly_name(conv->get_friendly_name());
ngraph::copy_runtime_info(conv, {input2d, weights2d, conv2d, reshape});
Expand All @@ -58,16 +63,16 @@ ngraph::matcher_pass_callback ov::intel_cpu::ConvertConv1DBase::convert_conv1d_t

ov::intel_cpu::ConvertConv1D::ConvertConv1D() {
auto m = std::make_shared<ngraph::pattern::Matcher>(
ngraph::pattern::wrap_type<ov::opset8::Convolution>({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()),
ngraph::pattern::any_input(ngraph::pattern::has_static_shape())},
ngraph::pattern::has_static_shape()), "ConvertConvolutionToArm");
ngraph::pattern::wrap_type<ov::opset8::Convolution>({ngraph::pattern::any_input(),
ngraph::pattern::any_input()}),
"ConvertConvolutionToArm");
register_matcher(m, convert_conv1d_to_conv2d<ov::opset8::Convolution>());
}

ov::intel_cpu::ConvertGroupConv1D::ConvertGroupConv1D() {
auto m = std::make_shared<ngraph::pattern::Matcher>(
ngraph::pattern::wrap_type<ov::opset8::GroupConvolution>({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()),
ngraph::pattern::any_input(ngraph::pattern::has_static_shape())},
ngraph::pattern::has_static_shape()), "ConvertGroupConvolutionToArm");
ngraph::pattern::wrap_type<ov::opset8::GroupConvolution>({ngraph::pattern::any_input(),
ngraph::pattern::any_input()}),
"ConvertGroupConvolutionToArm");
register_matcher(m, convert_conv1d_to_conv2d<ov::opset8::GroupConvolution>());
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,51 @@

#include <ngraph/pass/graph_rewrite.hpp>

/*
* Description:
* ConvertConv1DBase detects 1D Convolution / GroupConvolution and replaces
* it with the sequence Unsqueeze - 2D Convolution / GroupConvolution - Squeeze.
* Unsqueeze adds the additional dimension to Convolution inputs and Squeeze
* removes the additional dimention from the Convolution output.
*
* Before:
*
* +--------------+ +---------------+
* | Input tensor | | Kernel tensor |
* +-----------+--+ +-+-------------+
* | |
* +-v---------v-+
* | Convolution |
* +------+------+
* |
* +------v------+
* | Result |
* +-------------+
*
* After:
*
* +--------------+ +--------------+ +---------------+ +--------------+
* | Input tensor | | Constant (1) | | Kernel tensor | | Constant (1) |
* +-----------+--+ +-+------------+ +-----------+---+ +-+------------+
* | | | |
* +-v---------v-+ +-v---------v-+
* | Unsqueeze | | Unsqueeze |
* +------+------+ +------+------+
* | |
* +------v------------------------------------v------+ +--------------+
* | Convolution | | Constant (1) |
* +---------------------------------------------+----+ +-+------------+
* | |
* +-v---------v-+
* | Squeeze |
* +------+------+
* |
* +------v------+
* | Result |
* +-------------+
*
*/

namespace ov {
namespace intel_cpu {
class ConvertConv1DBase: public ngraph::pass::MatcherPass {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,26 @@ ngraph::matcher_pass_callback ov::intel_cpu::ConvertReduceMultiAxisBase::convert
if (!std::dynamic_pointer_cast<T>(reduce)) {
return false;
}
if (ngraph::shape_size(reduce->input_value(1).get_shape()) <= 1) {

const auto& input0 = reduce->input_value(0);
const auto& input1 = reduce->input_value(1);
const auto& data_shape0 = input0.get_partial_shape();
const auto& data_shape1 = input1.get_partial_shape();
if (data_shape0.is_dynamic() ||
data_shape1.is_dynamic()) {
return false;
}

if (ngraph::shape_size(input1.get_shape()) <= 1) {
return false;
}
auto reduction_axes = std::dynamic_pointer_cast<ov::opset8::Constant>(reduce->input_value(1).get_node_shared_ptr());
auto reduction_axes = std::dynamic_pointer_cast<ov::opset8::Constant>(input1.get_node_shared_ptr());
if (!reduction_axes) {
return false;
}
auto axes = reduction_axes->cast_vector<int64_t>();
ngraph::NodeVector new_ops;
std::shared_ptr<ngraph::Node> node = reduce->input_value(0).get_node_shared_ptr();
std::shared_ptr<ngraph::Node> node = input0.get_node_shared_ptr();
for (auto axis : axes) {
auto reduction_axis = ov::opset8::Constant::create<int64_t>(ngraph::element::i64, ngraph::Shape{}, {axis});
node = std::make_shared<T>(node, reduction_axis, true);
Expand All @@ -46,32 +56,28 @@ ngraph::matcher_pass_callback ov::intel_cpu::ConvertReduceMultiAxisBase::convert

ov::intel_cpu::ConvertReduceProd::ConvertReduceProd() {
auto m = std::make_shared<ngraph::pattern::Matcher>(
ngraph::pattern::wrap_type<ov::opset8::ReduceProd>({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()),
ngraph::pattern::wrap_type<ov::opset8::Constant>()},
ngraph::pattern::has_static_shape()), "ConvertReduceProd");
ngraph::pattern::wrap_type<ov::opset8::ReduceProd>({ngraph::pattern::any_input(),
ngraph::pattern::wrap_type<ov::opset8::Constant>()}), "ConvertReduceProd");
register_matcher(m, convert_reduce<ov::opset8::ReduceProd>());
}

ov::intel_cpu::ConvertReduceMin::ConvertReduceMin() {
auto m = std::make_shared<ngraph::pattern::Matcher>(
ngraph::pattern::wrap_type<ov::opset8::ReduceMin>({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()),
ngraph::pattern::wrap_type<ov::opset8::Constant>()},
ngraph::pattern::has_static_shape()), "ConvertReduceMin");
ngraph::pattern::wrap_type<ov::opset8::ReduceMin>({ngraph::pattern::any_input(),
ngraph::pattern::wrap_type<ov::opset8::Constant>()}), "ConvertReduceMin");
register_matcher(m, convert_reduce<ov::opset8::ReduceMin>());
}

ov::intel_cpu::ConvertReduceMax::ConvertReduceMax() {
auto m = std::make_shared<ngraph::pattern::Matcher>(
ngraph::pattern::wrap_type<ov::opset8::ReduceMax>({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()),
ngraph::pattern::wrap_type<ov::opset8::Constant>()},
ngraph::pattern::has_static_shape()), "ConvertReduceMax");
ngraph::pattern::wrap_type<ov::opset8::ReduceMax>({ngraph::pattern::any_input(),
ngraph::pattern::wrap_type<ov::opset8::Constant>()}), "ConvertReduceMax");
register_matcher(m, convert_reduce<ov::opset8::ReduceMax>());
}

ov::intel_cpu::ConvertReduceSum::ConvertReduceSum() {
auto m = std::make_shared<ngraph::pattern::Matcher>(
ngraph::pattern::wrap_type<ov::opset8::ReduceSum>({ngraph::pattern::any_input(ngraph::pattern::has_static_shape()),
ngraph::pattern::wrap_type<ov::opset8::Constant>()},
ngraph::pattern::has_static_shape()), "ConvertReduceSum");
ngraph::pattern::wrap_type<ov::opset8::ReduceSum>({ngraph::pattern::any_input(),
ngraph::pattern::wrap_type<ov::opset8::Constant>()}), "ConvertReduceSum");
register_matcher(m, convert_reduce<ov::opset8::ReduceSum>());
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,50 @@
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/pass/graph_rewrite.hpp>

/*
* Description:
* ConvertReduceMultiAxisBase detects Reduce operations that do not support
* multi-axis input by ACL: Min, Max, Sum, Prod. Multi-axis Reduce operation
* is replaced with a sequence of single-axe Reduce operations.
*
* Before:
*
* +--------------+ +-------------------+
* | Data | | Axes tensor [A,B] |
* +-----------+--+ +-+-----------------+
* | |
* +----v---------v----+
* | Reduce |
* +---------+---------+
* |
* +------v------+
* | Result |
* +-------------+
*
* After:
*
* +-------------+ +---------------+
* | Data | | Axes scalar A |
* +---------+---+ +----+----------+
* | |
* +-v------------v--+ +-----------------+
* | Reduce | | Axes scalar B |
* +--------------+--+ +---+-------------+
* | |
* +-v-----------v---+
* | Reduce |
* +-------+---------+
* |
* +-------v---------+
* | Reshape |
* +-------+---------+
* |
* +-------v---------+
* | Result |
* +-----------------+
*
*/

namespace ov {
namespace intel_cpu {

Expand Down
5 changes: 3 additions & 2 deletions src/plugins/intel_cpu/tests/functional/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ endif()
if(X86_64)
list(APPEND EXCLUDED_SOURCE_PATHS
${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests/instances/arm
${CMAKE_CURRENT_SOURCE_DIR}/subgraph_tests/arm)
${CMAKE_CURRENT_SOURCE_DIR}/subgraph_tests/src/arm)
else()
list(APPEND EXCLUDED_SOURCE_PATHS
${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests/instances/x64
${CMAKE_CURRENT_SOURCE_DIR}/subgraph_tests/x64)
${CMAKE_CURRENT_SOURCE_DIR}/subgraph_tests/src/x64)
# temporary disable all custom tests for ARM
list(APPEND EXCLUDED_SOURCE_PATHS
${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests
Expand All @@ -35,6 +35,7 @@ else()
file(GLOB_RECURSE TMP_LIST_OF_TEST_CLASSES ${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests/classes/*.cpp)
file(GLOB_RECURSE TMP_LIST_OF_COMMON_TEST_INSTANCES ${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests/instances/common/*.cpp)
file(GLOB_RECURSE TMP_LIST_OF_ARM_TEST_INSTANCES ${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests/instances/arm/*.cpp)
file(GLOB_RECURSE TMP_LIST_OF_ARM_TEST_INSTANCES ${CMAKE_CURRENT_SOURCE_DIR}/subgraph_tests/arm/*.cpp)
list(APPEND TMP_LIST_OF_EXPLICITLY_ENABLED_TESTS
${TMP_LIST_OF_TEST_CLASSES} ${TMP_LIST_OF_COMMON_TEST_INSTANCES} ${TMP_LIST_OF_ARM_TEST_INSTANCES})
set(TMP_EXPLICITLY_ENABLED_TESTS "${TMP_LIST_OF_EXPLICITLY_ENABLED_TESTS}")
Expand Down
Loading