Skip to content

[Transformations] Added interchangeable reshape elimination#9691

Merged
GlebKazantaev merged 6 commits intoopenvinotoolkit:masterfrom
a-sidorova:feature/transformations/reshape_elimination
Feb 9, 2022
Merged

[Transformations] Added interchangeable reshape elimination#9691
GlebKazantaev merged 6 commits intoopenvinotoolkit:masterfrom
a-sidorova:feature/transformations/reshape_elimination

Conversation

@a-sidorova
Copy link
Copy Markdown
Contributor

Details:

  • Updated transformation to eliminate interchangeable reshape nodes (Reshape, Squeeze, Unsqueeze).
  • Example:
    image

Tickets:

@a-sidorova a-sidorova requested review from a team January 17, 2022 06:38
@openvino-pushbot openvino-pushbot added category: CPU OpenVINO CPU plugin category: inference OpenVINO Runtime library - Inference category: IE Tests OpenVINO Test: plugins and common category: Core OpenVINO Core (aka ngraph) labels Jan 17, 2022
@a-sidorova a-sidorova added this to the 2022.1 milestone Jan 17, 2022
@dmitry-gorokhov
Copy link
Copy Markdown

@v-Golubev please review the PR
@GlebKazantaev would be great if you could take a look as well

@a-sidorova a-sidorova force-pushed the feature/transformations/reshape_elimination branch from f3fb719 to 53ae67c Compare January 20, 2022 17:11
@GlebKazantaev GlebKazantaev self-assigned this Jan 25, 2022
auto input_node = input.get_node_shared_ptr();
if (ov::as_type_ptr<opset3::Squeeze>(input_node) ||
ov::as_type_ptr<opset3::Unsqueeze>(input_node) ||
ov::as_type_ptr<opset3::Reshape>(input_node)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check wasn't precise as we don't check the number of consumers here, so we potentially could ruin the model.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added check for consumer count in this transformation

auto input_node = input.get_node_shared_ptr();
if (ov::as_type_ptr<opset3::Squeeze>(input_node) ||
ov::as_type_ptr<opset3::Unsqueeze>(input_node) ||
ov::as_type_ptr<opset3::Reshape>(input_node)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have dedicated transformation ReshapeSequenceFusion which performs such type of elimination, and this pass doesn't perform this fusion correctly in case of Reshape->Reshape pattern. So I suggest to remove Reshape from this condition.

Also we have to check that number of consumer is equal to 1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added check for consumer count in this transformation and removed Reshape from the condition.
But as I understand, transformation ReshapeSequenceFusion doesn't eliminate redundant reshapes, it always fuses into one reshape. So I updated ReshapeSequenceFusion transformation to cover interchangeable reshapes (to eliminate it)
Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I'm not sure about Reshape removing from this condition because transformation NopElimination contains EliminationSqueeze and EliminationUnsqueeze that convert Squeeze and Unsqueeze to Reshape. Moreover NopElimination contains EliminationReshape. And if we remove Reshape, using NopElimination we will have pattern Reshape->Reshape after Squeeze->Reshape, for example. Is it ok for NopElimination? What do you think?

if (!ngraph::op::util::has_op_with_type<ngraph::op::FakeQuantize>(nGraphFunc)) {
manager.register_pass<ReshapeFullyConnectedFusion>();
}
manager.register_pass<ngraph::pass::EliminateReshape>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If some transformation inserts such reshapes, so you can simply call this EliminateReshape().apply(reshape) from this pass.

ASSERT_TRUE(movement_are_missing);
}

TEST(nop_elimination, squeeze_unsqueeze_elimination) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't insist but in most tests we use TEST_F(TransformationTestsF fixture, so we don't have to check everything manually.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains only TEST(nop_elimination) so I created test using this fixture. But I decided to create new test for updated transformation ReshapeSequenceFusion (because I added elimination support for redundant reorders) and I used TEST_F(TransformationTestsF fixture for it. Thanks!

@a-sidorova a-sidorova force-pushed the feature/transformations/reshape_elimination branch from 53ae67c to 43a5903 Compare January 26, 2022 07:23

// eliminate redundant reshape, squeeze, or unsqueeze
auto input_node = input.get_node_shared_ptr();
if (input_node->get_output_size() != 1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't check the number of consumers, as get_output_size returns number of output ports but not consumers. Please use get_target_inputs after you casted input node to one of this reshape like operations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And please add a tests for this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got it, thank you very much!
Added get_output_target_inputs and added test reshape_elimination_v1_check_consumer_count for this case.

Comment on lines +62 to +102
if (input.get_node_shared_ptr()->get_output_partial_shape(0).is_static() && reshape->get_output_partial_shape(0).is_static() &&
input.get_node_shared_ptr()->get_output_shape(0) == reshape->get_output_shape(0)) {
return replace_output_update_name(reshape->output(0), input);
} else {
reshape->input(0).replace_source_output(input);
copy_runtime_info(nodes, reshape);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input is already an Output class so you can get partial shape from it.
Also as this transformation is included into MOC pipeline where we can rely on shapes only in case if use_shape is true, so we have to parametrize transformation (for example: https://github.com/openvinotoolkit/openvino/blob/master/src/common/transformations/include/transformations/common_optimizations/split_concat_pair_to_interpolate_fusion.hpp#L32 )

Suggested change
if (input.get_node_shared_ptr()->get_output_partial_shape(0).is_static() && reshape->get_output_partial_shape(0).is_static() &&
input.get_node_shared_ptr()->get_output_shape(0) == reshape->get_output_shape(0)) {
return replace_output_update_name(reshape->output(0), input);
} else {
reshape->input(0).replace_source_output(input);
copy_runtime_info(nodes, reshape);
}
bool replaced = false;
if (use_shapes && input.get_partial_shape().is_static() && reshape->get_output_partial_shape(0).is_static() &&
input.get_shape() == reshape->get_output_shape(0)) {
// in case if elimination is not allowed we still can eliminate all transposes except last one
replaced = replace_output_update_name(reshape->output(0), input));
}
if (!replaced) {
reshape->input(0).replace_source_output(input);
copy_runtime_info(nodes, reshape);
}

Also please add tests for this case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation!
Done.
About test - Before I added test ReshapeSequenceFusionEliminate that covers case when we can remove 2 redundant reorders. I think it's enough

@a-sidorova a-sidorova force-pushed the feature/transformations/reshape_elimination branch from 7bace72 to 365386b Compare January 28, 2022 15:57
@a-sidorova a-sidorova force-pushed the feature/transformations/reshape_elimination branch 2 times, most recently from 5c92007 to ab1ffc4 Compare February 2, 2022 08:42
@a-sidorova
Copy link
Copy Markdown
Contributor Author

@GlebKazantaev take a look one more time please

@a-sidorova a-sidorova force-pushed the feature/transformations/reshape_elimination branch from ab1ffc4 to 642822f Compare February 7, 2022 06:25
copy_runtime_info(nodes, reshape);
}

return false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return false;
return true;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


if (!replaced) {
reshape->input(0).replace_source_output(input);
copy_runtime_info(nodes, reshape);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
copy_runtime_info(nodes, reshape);
copy_runtime_info(nodes, reshape);
return false; // because root node wasn't replaced

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thank you

public:
NGRAPH_RTTI_DECLARATION;
ReshapeSequenceFusion();
ReshapeSequenceFusion(bool use_shape_for_elimination = true);
Copy link
Copy Markdown
Contributor

@GlebKazantaev GlebKazantaev Feb 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update moc_transformations.cpp
https://github.com/openvinotoolkit/openvino/blob/master/src/common/transformations/src/transformations/common_optimizations/moc_transformations.cpp#L156

common_fusions->add_matcher<ngraph::pass::ReshapeSequenceFusion>(m_use_shapes);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, thanks

@GlebKazantaev
Copy link
Copy Markdown
Contributor

In general LGTM, just some small comments remaining and we can merge.

@a-sidorova a-sidorova force-pushed the feature/transformations/reshape_elimination branch from 642822f to e81d505 Compare February 9, 2022 06:51
@GlebKazantaev GlebKazantaev merged commit fce49e6 into openvinotoolkit:master Feb 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: Core OpenVINO Core (aka ngraph) category: CPU OpenVINO CPU plugin category: IE Tests OpenVINO Test: plugins and common category: inference OpenVINO Runtime library - Inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants