Remove the deprecated MPS backend - #22181
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22181
Note: Links to docs will display an error until the docs builds have been completed. ❌ 1 New Failure, 155 Pending, 1 Unrelated FailureAs of commit 5f8cfbd with merge base 04b3446 ( NEW FAILURE - The following job has failed:
BROKEN TRUNK - The following job failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
|
The SwiftPM package needs a matching change, opened separately because it lives That branch holds Worth flagging because the failure is quiet and affects everyone: the manifest The two can land in either order. The artifact is live today, so this is a real |
12b1cef to
c83acaa
Compare
|
Thanks, all three findings were correct and are fixed. I reproduced each one 1, the broken table. Confirmed and it was worse than a bad row. Building the Exit 0, and the rendered page contained zero Fixed by deleting the row outright, since Metal GPU on iOS has no backend to 2, the torchao claim. You are right and my sentence was wrong. It is stronger Since it cannot outlive the backend, I removed 3, the sweep. Also correct, and the cause is instructive: I swept for On the scope creep. Fair, and checking it found a real problem: MLX needs an I left Separately, your point about |
c83acaa to
0cb2a75
Compare
0cb2a75 to
f7752bf
Compare
f7752bf to
7e10142
Compare
|
Updated after review. All five documentation and comment findings are fixed, and The redirect comment promised something the target does not offer. It said old The build example no longer illustrated its own sentence. The sentence is about A stale comment explained live code by naming the deleted backend Two commit message claims were wrong:
One finding I am deliberately not acting on, with the reasoning, since a
On landing order: agreed, and #22182 should go first. The nightly cron makes the |
7e10142 to
5a36594
Compare
|
Second round addressed. Two new items, both verified independently before acting. C1 is correctly a blocker, and the fix already committed is the one you Worth recording that my first attempt at this reproduction produced a false R3 checks out, and it strengthens the case for #22182 rather than sitting So this mechanism has already produced a real multi-day outage, for a different Because of that I took the optional guard you suggested rather than leaving it. The C5a is real and needs no code change. Confirmed Note the new guard also limits the C5a exposure: a |
|
C7 and C8 are both already fixed on the current head; I think the re-read caught the For C8 specifically, the message now distinguishes the two cases your measurement C9 I am still not acting on, and here is the reasoning rather than silence. The runtime kernels for the ops Narrowing the accepted CLI patterns is a real cleanup and I agree it will cost |
5a36594 to
8b862bc
Compare
The MPS backend was deprecated in ExecuTorch 1.2 and its own deprecation notices say it will be removed in 1.4. The tree is now at 1.5.0, so the removal is overdue. Delete it. MPS delegated model execution to Apple's MPSGraph framework. The replacements its deprecation notice names are still here: Core ML for general Apple acceleration, and the Metal backend for macOS GPU work. What goes away: - `backends/apple/mps/` and `examples/apple/mps/` - the `EXECUTORCH_BUILD_MPS` build option, and the places that set it - the `backend_mps` SwiftPM product and its Apple framework build rules - the `--mps` export flag, the `backend.mps.enabled` config key, and `get_mps_partitioner` - the MPS CI jobs, benchmark configurations, and documentation pages - `EXECUTORCH_BUILD_KERNELS_TORCHAO_MPS`, which built torchao's Metal kernels for this runtime. Those kernels include a header from this backend and call into its namespace, so they cannot outlive it. The option was off by default and set by nothing in the tree. Two things that look like MPS are deliberately kept, because they are unrelated to this backend: - The Metal backend links Apple's MetalPerformanceShaders framework directly for some fallback operations. That is a system library, not this delegate. - `TORCHAO_BUILD_EXPERIMENTAL_MPS` builds torchao's own Metal kernels for eager PyTorch. It never sets `TORCHAO_BUILD_EXECUTORCH_OPS`, so it does not reach the variant that depended on this backend. `--device mps` in an export script is PyTorch's device name for Apple GPUs, and `MPS` in a codegen fixture is a PyTorch dispatch key. Both stay. Removed documentation pages redirect to the backend overview, which lists the Apple alternatives, rather than returning 404. Callers passing `-DEXECUTORCH_BUILD_MPS=ON` will find the option is gone. CMake reports it as an unused variable rather than failing, and the build produces a runtime without the backend, which is the correct end state. The `--mps` flag of the Apple framework script is rejected outright, since that script validates its arguments. Test Plan: No test exercises this backend after the change, so verification focused on proving nothing else broke. Configured the Apple build and the LLM build to completion. Both previously turned this backend on by default, and both configure with it absent. Then built and linked the example runner: it contains no symbol from this backend, still registers Core ML and XNNPACK, and runs a delegated model to the correct result. The two source lists in the build glue are consumed positionally, so both were checked to still be the same length, and every list name the build asks for was confirmed to still resolve. Ran the benchmark configuration logic directly: the iOS configuration list no longer offers this backend, one model's expected list matches, and no disabled entry names a configuration that no longer exists. Parsed the changed workflow files as YAML and confirmed no job remains. Parsed both Xcode projects and confirmed no reference to the removed package product and no dangling object references. Checked the SwiftPM manifest still has a stub directory for every product it declares, and no orphan directories. Built the affected documentation table with Sphinx and MyST to confirm it still renders as a table rather than being replaced by a parse error, which is what a row with the wrong number of cells causes. Confirmed every redirect target resolves to a real page, and that no remaining cross-reference points at a deleted one. Syntax-checked the changed shell scripts, and confirmed formatting and lint are clean on the changed Python, CMake and HTML files. Finally, swept the tree with a word-boundary search rather than a token search, and audited every remaining match. What remains is PyTorch's device name, a PyTorch dispatch key, torchao's eager Metal kernels, tokenizer vocabulary entries, Arm Corstone board names, and historical notes under `.wiki/`. Also make the SwiftPM release step check that the manifest and the built frameworks describe the same set, in both directions, since each failure is silent on its own. A placeholder with no framework publishes literal text where a checksum belongs: eight consecutive nightly manifests in August 2025 shipped that way, which makes the package unresolvable for every consumer rather than only users of that product. A framework with no product is the reverse, and matters here because release branches share one template, so a branch that still builds a removed framework would drop the product from the manifest silently. Both checks run only on a publishing run, so a template that is momentarily out of step with a branch does not redden unrelated pull requests. Removing a framework is exactly the change that exercises this, so the guard belongs with it. Verified the guard against the real manifests from that incident: it fails on the affected days, naming the surviving placeholders, and passes on the day the incident ended. The guard compares each built framework against the product base name, because the manifest declares each product once and synthesises its debug variant in Swift.
8b862bc to
5f8cfbd
Compare
The MPS delegate was removed from ExecuTorch in pytorch/executorch#22181, so nothing produces mv3_mps_float16.pte any more and no backend_mps SwiftPM product is published. The mv3 demo still declared both, which fails the build before it starts: error: .../Resources/Models/MobileNet/mv3_mps_float16.pte: No such file or directory (in target 'App' from project 'ExecuTorchDemo') That is the build-demo-ios job on executorch main, which has been red since that change landed. Drop the product references from both Xcode projects, the model resource and the picker case from the mv3 demo, and the export that produced the file. The export was already misleading: the MPS path had been commented out and the program was re-exported with portable ops under an mps name, so the option ran the same graph as the portable build while claiming to be GPU accelerated. The Metal references under voxtral_realtime/ are deliberately left alone. Those are TORCHAO_BUILD_EXPERIMENTAL_MPS, a torchao Metal-kernel flag that the Metal backend still uses upstream, not the removed delegate. Test Plan: No MPS reference remains outside voxtral_realtime/, checked with a word-boundary grep over every file type. Both Xcode projects lint clean with plutil, and their object graphs are intact: 109 objects in mv3 and 63 in etLLM, with zero ids referenced but not defined and zero defined but never referenced. The originals measured the same way, so the edit preserved the property rather than happening to satisfy it. Confirmed backend_coreml and backend_xnnpack survive in both. ClassificationController.swift parses with swiftc, and the switch over Mode is still exhaustive over the two remaining cases. Nothing else referenced Mode.mps; MobileNetClassifierTest covers portable, Core ML and XNNPACK and never had an MPS case. export.py compiles and the workflow artifact list no longer names the file it stopped producing. Co-authored-by: Devmate <devmate@meta.com>
The MPS backend was deprecated in ExecuTorch 1.2 and its own deprecation
notices say it will be removed in 1.4. The tree is now at 1.5.0, so the
removal is overdue. Delete it.
MPS delegated model execution to Apple's MPSGraph framework. The replacements
its deprecation notice names are still here: Core ML for general Apple
acceleration, and the Metal backend for macOS GPU work.
What goes away:
backends/apple/mps/andexamples/apple/mps/EXECUTORCH_BUILD_MPSbuild option, and the places that set itbackend_mpsSwiftPM product and its Apple framework build rules--mpsexport flag, thebackend.mps.enabledconfig key, andget_mps_partitionerEXECUTORCH_BUILD_KERNELS_TORCHAO_MPS, which built torchao's Metal kernelsfor this runtime. Those kernels include a header from this backend and call
into its namespace, so they cannot outlive it. The option was off by default
and set by nothing in the tree.
Two things that look like MPS are deliberately kept, because they are unrelated
to this backend:
some fallback operations. That is a system library, not this delegate.
TORCHAO_BUILD_EXPERIMENTAL_MPSbuilds torchao's own Metal kernels for eagerPyTorch. It never sets
TORCHAO_BUILD_EXECUTORCH_OPS, so it does not reachthe variant that depended on this backend.
--device mpsin an export script is PyTorch's device name for Apple GPUs, andMPSin a codegen fixture is a PyTorch dispatch key. Both stay.Removed documentation pages redirect to the backend overview, which lists the
Apple alternatives, rather than returning 404.
Callers passing
-DEXECUTORCH_BUILD_MPS=ONwill find the option is gone. CMakereports it as an unused variable rather than failing, and the build produces a
runtime without the backend, which is the correct end state. The
--mpsflag ofthe Apple framework script is rejected outright, since that script validates its
arguments.
Test Plan:
No test exercises this backend after the change, so verification focused on
proving nothing else broke.
Configured the Apple build and the LLM build to completion. Both previously
turned this backend on by default, and both configure with it absent. Then built
and linked the example runner: it contains no symbol from this backend, still
registers Core ML and XNNPACK, and runs a delegated model to the correct result.
The two source lists in the build glue are consumed positionally, so both were
checked to still be the same length, and every list name the build asks for was
confirmed to still resolve.
Ran the benchmark configuration logic directly: the iOS configuration list no
longer offers this backend, one model's expected list matches, and no disabled
entry names a configuration that no longer exists.
Parsed the changed workflow files as YAML and confirmed no job remains. Parsed
both Xcode projects and confirmed no reference to the removed package product
and no dangling object references. Checked the SwiftPM manifest still has a stub
directory for every product it declares, and no orphan directories.
Built the affected documentation table with Sphinx and MyST to confirm it still
renders as a table rather than being replaced by a parse error, which is what a
row with the wrong number of cells causes. Confirmed every redirect target
resolves to a real page, and that no remaining cross-reference points at a
deleted one.
Syntax-checked the changed shell scripts, and confirmed formatting and lint are
clean on the changed Python, CMake and HTML files.
Finally, swept the tree with a word-boundary search rather than a token search,
and audited every remaining match. What remains is PyTorch's device name, a
PyTorch dispatch key, torchao's eager Metal kernels, tokenizer vocabulary
entries, Arm Corstone board names, and historical notes under
.wiki/.Also make the SwiftPM release step check that the manifest and the built frameworks
describe the same set, in both directions, since each failure is silent on its own.
A placeholder with no framework publishes literal text where a checksum belongs:
eight consecutive nightly manifests in August 2025 shipped that way, which makes the
package unresolvable for every consumer rather than only users of that product. A
framework with no product is the reverse, and matters here because release branches
share one template, so a branch that still builds a removed framework would drop the
product from the manifest silently. Both checks run only on a publishing run, so a
template that is momentarily out of step with a branch does not redden unrelated
pull requests. Removing a framework is exactly the change that exercises this, so
the guard belongs with it.
Verified the guard against the real manifests from that incident: it fails on the
affected days, naming the surviving placeholders, and passes on the day the
incident ended.
The guard compares each built framework against the product base name, because the
manifest declares each product once and synthesises its debug variant in Swift.
The SwiftPM package needs a matching change on its own branch: #22182.