Skip to content

Generalize reshape fusion#3554

Merged
snnn merged 2 commits into
microsoft:masterfrom
MaximKalininMS:makalini/generalize-reshape-fusion
Apr 19, 2020
Merged

Generalize reshape fusion#3554
snnn merged 2 commits into
microsoft:masterfrom
MaximKalininMS:makalini/generalize-reshape-fusion

Conversation

@MaximKalininMS
Copy link
Copy Markdown
Contributor

Description: Generalize reshape fusion.

Motivation and Context
Currently, reshape fusion works with a very specific graph pattern. This change will:

  • Allow arbitrary number of Concat arguments
  • Apply fusion even when an output of an internal node is used elsewhere
  • Fix a bug when an internal node's output is the subgraph output
  • Simplify code

See source code comments for details.

* Allow arbitrary number of Concat arguments
* Apply fusion even when an output of an internal node is used elsewhere
* Fix a bug when an internal node's output is the subgraph output
* Simplify code
@MaximKalininMS MaximKalininMS requested a review from a team as a code owner April 16, 2020 18:08
yufenglee
yufenglee previously approved these changes Apr 16, 2020
Copy link
Copy Markdown
Member

@yufenglee yufenglee left a comment

Choose a reason for hiding this comment

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

:shipit:

shape_value.reserve(concat_input_count);
// Used to keep the following nodes in the order of their potential removal.
enum class NodeType { Unsqueeze, Gather, Shape };
std::set<std::pair<NodeType, NodeIndex>> candidates_for_removal;
Copy link
Copy Markdown
Contributor

@tianleiwu tianleiwu Apr 16, 2020

Choose a reason for hiding this comment

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

candidates_for_removal can be std::vector<NodeIndex>. Then append node index of unsqueeze, gather, shape nodes in the order.

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 will not work correctly in case of sharing, e.g. when different Gather nodes refer to the same Shape 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.

That's right. That need check node index does not exist in the vector before appending (to avoid duplicated node index).

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.

Then the vector will be in the order [unsqueeze1, gather1, shared_shape, unsqueeze2, gather2], which is incorrect because we want to remove nodes in reverse topological order (unsqueeze2 and gather2 must come before shared_shape).

tianleiwu
tianleiwu previously approved these changes Apr 16, 2020
@yufenglee
Copy link
Copy Markdown
Member

/azp run Linux CPU CI Pipeline,Linux GPU CI Pipeline,Linux GPU TensorRT CI Pipeline,MacOS CI Pipeline,Win CPU x86 CI Pipeline,Windows GPU CI Pipeline,Windows GPU TensorRT CI Pipeline,Win CPU x64 NoContribops CI Pipeline,MacOS NoContribops CI Pipeline,Linux CPU x64 NoContribops CI Pipeline

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 8 pipeline(s).

@MaximKalininMS MaximKalininMS dismissed stale reviews from tianleiwu and yufenglee via f5e7e60 April 16, 2020 22:34
@snnn
Copy link
Copy Markdown
Contributor

snnn commented Apr 19, 2020

/azp run Linux CPU CI Pipeline,Linux GPU CI Pipeline,Linux GPU TensorRT CI Pipeline,MacOS CI Pipeline,Windows GPU CI Pipeline,Windows GPU TensorRT CI Pipeline,MacOS NoContribops CI Pipeline,Linux CPU x64 NoContribops CI Pipeline,Windows CPU CI Pipeline

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 9 pipeline(s).

@snnn snnn merged commit fcf0f6e into microsoft:master Apr 19, 2020

if (concat_input_count > 3) {
if (!optimizer_utils::AppendTensorFromInitializer(graph, *(concat.InputDefs()[3]), shape_value)) {
if (!optimizer_utils::IsInitializerWithExpectedValue(graph, *(gather.InputDefs()[1]), int64_t(i), 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.

The expected value should be shape_value.size() instead of i because the tensor appended in line 97 could have multiple elements. @MaximKalininMS, could you provide a fix?

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.

Thanks for catching it! Sent #3721

MaximKalininMS added a commit to MaximKalininMS/onnxruntime that referenced this pull request Apr 27, 2020
microsoft#3554 introduced a bug:
initializers can now come before Shape->Gather->Unsqueeze chains; if
those initializers have more than 1 element, expected dimensions in the
chains are now incorrect.
tianleiwu added a commit that referenced this pull request May 2, 2020
* Fix a crash in Reshape
Reshape doesn't handle 0 input dimension properly, which leads to a
division by zero

* Fix reshape fusion
#3554 introduced a bug:
initializers can now come before Shape->Gather->Unsqueeze chains; if
those initializers have more than 1 element, expected dimensions in the
chains are now incorrect.

Authored-by: Max Kalinin <makalini@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants