merge_consecutive_reshapes: do not merge past a trailing shape containing 0 - #2790
Open
LeSingh1 wants to merge 1 commit into
Open
merge_consecutive_reshapes: do not merge past a trailing shape containing 0#2790LeSingh1 wants to merge 1 commit into
LeSingh1 wants to merge 1 commit into
Conversation
…ning 0
A 0 in reshape's shape means "inherit the corresponding dimension from x.shape"
(see the reshape op docstring). The merged reshape takes its shape from the last
op of the sequence but its input from the first, so a trailing 0 gets re-bound to
a different tensor and the model's output shape silently changes:
@mb.program(input_specs=[mb.TensorSpec(shape=(2, 3, 4))])
def prog(x):
y = mb.reshape(x=x, shape=(4, 3, 2))
return mb.reshape(x=y, shape=(0, 6, -1))
['reshape', 'reshape'] -> ['reshape'], output shape (4, 6, 1) -> (2, 6, 2)
The 0 originally inherited dim 0 of (4, 3, 2); after the merge it inherits dim 0
of (2, 3, 4).
Trim such ops off the end of the matched sequence rather than rejecting the whole
sequence, so the reshapes before the offending one still merge. A 0 anywhere but
the last position is discarded by the merge and remains harmless.
When the shape is not known at compile time we cannot tell whether it holds a 0;
that case keeps the existing behavior.
common::merge_consecutive_reshapes is in the default pipeline.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Per the
reshapeop's own docstring, a0inshapemeans "ifK == rank(x)then0means inheriting from the corresponding dimension inx.shape".merge_consecutive_reshapesbuilds the merged op asmb.reshape(x=reshape_ops[0].x, shape=reshape_ops[-1].shape)— shape from the last op of the sequence, input from the first. So a0in the trailing shape is re-bound to a different tensor and the model's output shape silently changes:The
0originally inherited dim 0 of(4, 3, 2)= 4; after the merge it inherits dim 0 of(2, 3, 4)= 2. The-1then absorbs the difference, so the volume still checks out and nothing raises — the converted model just has a different output shape than the program it was built from.common::merge_consecutive_reshapesis in the default pipeline (pass_pipeline.py).Fix
Trim ops whose shape contains a
0off the end of the matched sequence, rather than rejecting the sequence outright. Only the trailing position matters — a0anywhere earlier has its shape discarded by the merge and stays harmless — so the reshapes before the offending one still merge and the optimization is preserved as far as it is valid.When the shape is not known at compile time (
shape.sym_val is None) we cannot tell whether it holds a0; that case keeps the existing behaviour rather than disabling the merge for all dynamically-shaped reshapes.Tests
In
TestMergeConsecutiveReshapes:test_keep_trailing_reshape_inheriting_input_dims— the repro above; both reshapes must survive and the output shape must stay(4, 6, 1). Fails onmain.test_merge_up_to_reshape_inheriting_input_dims— three reshapes with a0in the last; the first two must still merge, leaving two ops. Fails onmain.test_merge_reshape_with_leading_zero_shape— a0in the first reshape must not block the merge (guards against over-narrowing). Passes before and after.The existing tests in the class are untouched. I ran the whole class before and after; the failure sets are identical (this environment cannot load CoreML.framework, so the
assert_model_is_validpredictions fail there either way — the graph-structure assertions preceding them all run and pass).Note: this touches
optimize_repeat_ops.py, which my PR #2784 also modifies, in a different class.