fix(MemoryFormatOpsPass): preserve input dim_order for clone/to_copy with no memory_format kwarg#17611
Conversation
…with no memory_format kwarg Issue pytorch#16032: clone() and _to_copy operations with no explicit memory_format kwarg were defaulting to contiguous dim_order, causing runtime assertion failures when cloning channels-last tensors. Changes: - Default memory_format to torch.preserve_format instead of torch.contiguous_format - When preserve_format, derive dim_order from input tensor's dim_order() - Simplify type annotation: dim_order is always assigned, no Optional needed Tests: - test_clone_no_kwarg_preserves_channels_last_dim_order: core repro case - test_clone_contiguous_format_kwarg_stays_contiguous: regression guard - test_to_copy_no_kwarg_preserves_channels_last_dim_order: _to_copy path
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/17611
Note: Links to docs will display an error until the docs builds have been completed. ❌ 2 New FailuresAs of commit 4f91bc4 with merge base 9f2f005 ( NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@pytorchbot label "release notes: exir" |
|
Request to the reviewers: Could you please add @GregoryComer as well? I have received very helpful advice from him in the other PR and it makes sense to have him also here so he can edit if needed. Note that some of the other changes will still be handled in another PR (where it also makes sense to have him review). |
GregoryComer
left a comment
There was a problem hiding this comment.
@nefainl Thanks for the update. This PR looks good, we can merge with a few small changes.
In addition to the few small nits, can you update the tests to also run the model and verify that the output tensor has the correct memory format / dim order?
@GregoryComer Thank you for looking into it, I will implement your suggestions and look into the lint runner output tomorrow and make the required fixes! |
|
Correction, I will look in detail at all the failing checks to see how to resolve them tomorrow. |
Thanks. You can ignore the samsung failures. The other failures (except lint) look like flakes. I'll re-try the jobs. |
|
Quick update on this PR:
Locally, the new
Let me know if you’d like any additional end-to-end checks (e.g. running the exported graph and inspecting runtime |
Clarify preserve_format behavior and extend MemoryFormatOpsPass tests to run the models and assert that output tensors have the expected memory format / dim order.
Replace the generator-based dim_order construction with a list comprehension to satisfy FLAKE8 C400 and add the missing blank line before the new test class to align with PEP 8 spacing.
Thanks a lot for the input and the helpful review comments / nits etc. I think I have covered all now. If you see any additional items please let me know! |
|
Each of the three
So we’re already checking both runtime output layout and export metadata. If you’d like additional end-to-end checks (e.g. running the exported ExecuTorch program and inspecting runtime |
|
Thanks - looks good. I'm going to run a few more tests and I'll merge if everything looks good. |
|
@GregoryComer has imported this pull request. If you are a Meta employee, you can view this in D95409924. |
Great, thanks for your help earlier in the solution direction! I will look into the other PR in more detail later. |
…with no memory_format kwarg (pytorch#17611) ## Summary Fixes pytorch#16032 This PR fixes `MemoryFormatOpsPass` to correctly handle `torch.preserve_format` semantics for `clone()` and `_to_copy.default` operations. **Root cause:** When `clone()` or `_to_copy` is called without an explicit `memory_format` kwarg, the pass was defaulting to `torch.contiguous_format`, causing the output `dim_order` to be `[0,1,2,3]` (contiguous) even when the input was channels-last `[0,2,3,1]`. This caused runtime assertion failures: ``` Code=18 InvalidArgument: tensors_have_same_dim_order(self, out) ``` **Fix:** Change the default from `torch.contiguous_format` to `torch.preserve_format`, and derive `dim_order` from the input tensor's `dim_order()` when preserve_format is used. This is a minimal, focused fix following the guidance from @GregoryComer in the discussion on PR pytorch#17463. ## Changes - **`exir/passes/memory_format_ops_pass.py`** (+29/-5 lines): - Default `memory_format` to `torch.preserve_format` instead of `torch.contiguous_format` - When preserve_format, derive `dim_order` from `input_tensor.dim_order()` - Fallback to contiguous if no input tensor available (e.g., `empty()`) - **`exir/tests/test_passes.py`** (+130 lines): - `test_clone_no_kwarg_preserves_channels_last_dim_order`: Core repro case for pytorch#16032 - `test_clone_contiguous_format_kwarg_stays_contiguous`: Regression guard - `test_to_copy_no_kwarg_preserves_channels_last_dim_order`: Verifies `_to_copy.default` path ## Standalone Reproduction ```python import torch from torch.export import export from executorch.exir import to_edge, EdgeCompileConfig class ConvClone(torch.nn.Module): def __init__(self): super().__init__() self.conv = torch.nn.Conv2d(3, 16, kernel_size=3, padding=1) def forward(self, x): return self.conv(x).clone() model = ConvClone().to(memory_format=torch.channels_last) x = torch.randn(1, 3, 8, 8).to(memory_format=torch.channels_last) exported = export(model, (x,)) edge = to_edge(exported, compile_config=EdgeCompileConfig(_skip_dim_order=False)) # Before fix: clone node has dim_order=(0,1,2,3) - BUG # After fix: clone node has dim_order=(0,2,3,1) - CORRECT for node in edge.exported_program().graph_module.graph.nodes: if "_clone_dim_order" in str(node.target): print(f"clone dim_order: {tuple(node.meta['val'].dim_order())}") ``` ## Test Plan - [x] All 3 new tests pass - [x] Verified fix with standalone reproduction script - [x] No changes to existing tests required ## Related - Fixes pytorch#16032 - Supersedes pytorch#17463 (this is the minimal fix extracted from that PR per reviewer feedback) --------- Co-authored-by: NefAI <info@nefai.nl>
Summary
Fixes #16032
This PR fixes
MemoryFormatOpsPassto correctly handletorch.preserve_formatsemantics forclone()and_to_copy.defaultoperations.Root cause: When
clone()or_to_copyis called without an explicitmemory_formatkwarg, the pass was defaulting totorch.contiguous_format, causing the outputdim_orderto be[0,1,2,3](contiguous) even when the input was channels-last[0,2,3,1]. This caused runtime assertion failures:Fix: Change the default from
torch.contiguous_formattotorch.preserve_format, and derivedim_orderfrom the input tensor'sdim_order()when preserve_format is used.This is a minimal, focused fix following the guidance from @GregoryComer in the discussion on PR #17463.
Changes
exir/passes/memory_format_ops_pass.py(+29/-5 lines):memory_formattotorch.preserve_formatinstead oftorch.contiguous_formatdim_orderfrominput_tensor.dim_order()empty())exir/tests/test_passes.py(+130 lines):test_clone_no_kwarg_preserves_channels_last_dim_order: Core repro case for Dim Order Validation Inconsistency for Edge / Ambiguous Cases #16032test_clone_contiguous_format_kwarg_stays_contiguous: Regression guardtest_to_copy_no_kwarg_preserves_channels_last_dim_order: Verifies_to_copy.defaultpathStandalone Reproduction
Test Plan
Related