Skip argmin/argmax with dim=None in CoreML partitioner#19247
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/19247
Note: Links to docs will display an error until the docs builds have been completed. ❗ 1 Active SEVsThere are 1 currently active SEVs. If your PR is affected, please view them below: This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
Hi @john-rocky! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
|
@pytorchbot label "release notes: apple" |
| # https://github.com/pytorch/executorch/issues/11715 | ||
| # argmin/argmax with dim=None reduces over the flattened input, which | ||
| # CoreML does not support and causes intermittent process crashes. | ||
| if node.target in [ |
There was a problem hiding this comment.
Can we factor this out into a utility that gets called here, e.g., is_arg_min_max_over_flattened_input
|
@john-rocky do you know what causes the crash in CoreML? |
|
Honest answer: not at the CoreML internals level. The original repro in #11715 (filed by @GregoryComer) is a 100%-reproducible segfault on M1 Pro when The conservative read is that CoreML's full-reduction-as- I'm happy to file an internal CoreML bug if you want to chase the runtime cause, but the partitioner-side mitigation seemed worth doing independently. |
Sounds good. I was just curious if you reproed the issue with coremltools directly, or ran lldb on the process to find the thing causing the runtime crash. |
|
This PR looks good @john-rocky. We can hopefully merge sometime next week when our CI is clean again. (And to confirm: you tested both argmax/argmin have an issue with None today?) |
|
Yes — both class FlatModel(torch.nn.Module):
def forward(self, x):
return torch.argmax(x, dim=None, keepdim=False) + torch.argmin(x, dim=None)and asserts both I haven't independently runtime-reproduced the segfault for |
I think there's now a merge conflict from your other PR :)
Did you reproduce either of these crashes on any device? The issue is quite old, and I don't know if CoreML has fixed it since in a new version of macOS/iOS? |
Closes pytorch#11715. argmax / argmin with dim=None reduce over the flattened input; coremltools 9.0 lowers this branch incorrectly on current macOS — the resulting CoreML model returns a per-row argmax of shape (N,) instead of the PyTorch-style scalar. The partitioner now rejects these so they fall back to the portable backend, while ordinary dim=int argmax/argmin still delegates.
a01c061 to
b520067
Compare
|
Rebased — branch is now a single squashed commit ( On the repro question: tested on macOS 26 / coremltools 9.0 by bypassing the partitioner skip and running The original process-crash from #11715 is gone, but the lowered model now silently returns a per-row argmax (shape Happy to add a note in the partitioner docstring linking to this thread if that helps future readers. |
Summary
argmax(x, dim=None)/argmin(x, dim=None)reduces over the flattenedtensor. CoreML does not support this reduction, and the resulting model
intermittently crashes the process at runtime (the issue reproducer
crashes 100% of the time on M1 Pro when the cell is run twice).
Detect the
dim is Nonecase inshould_override_supportso the opfalls back to the portable backend. The ordinary
dim=intform isunaffected and still gets delegated.
Fixes #11715.
Test plan
Added
test_argmax_argmin_dim_none_is_skippedcovering both branches:argmax(x, dim=None) + argmin(x, dim=None)— neither op is delegated.argmax(x, dim=1)— gets delegated as before.Authored with Claude.
cc @metascroy