Cache backend FakeTensor dispatches during ExportPass replay (#21700) - #21700
Cache backend FakeTensor dispatches during ExportPass replay (#21700)#21700apullin wants to merge 2 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21700
Note: Links to docs will display an error until the docs builds have been completed. ❌ 7 New FailuresAs of commit 173c7bd with merge base fb5eedc ( NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@apullin has exported this pull request. If you are a Meta employee, you can view the originating Diff in D115374097. |
This PR needs a
|
…#21700) Summary: Split from D97528110 so the FakeTensor cache extension can be reviewed independently from cold-node fast-copy. `FakeTensorMode` normally caches only `aten`, `prim`, and `prims` operations. ExportPass replay repeatedly dispatches deterministic backend operators from `quantized_decomposed`, `tosa`, and `cortex_m`, but PyTorch stores `non-builtin` negative cache entries for them. This change temporarily extends `torch._library.utils.is_builtin` while ExportPass runs, evicts only matching `non-builtin` bypass entries from the class-global and active ShapeEnv caches, and restores the exact original predicate in `finally`. Positive entries remain available across successive passes, which is the source of the speedup. This intentionally remains a narrow process-global monkeypatch. Current `FakeTensorMode` has no per-instance cache-policy hook, and its non-symbolic cache is class-global. The reentrant lock serializes participating ExportPass contexts, but unrelated threads can observe the extended predicate while the context is active. Fully isolated behavior requires an upstream policy hook plus cache-policy identity or per-mode cache storage; keeping this in a separate diff makes that tradeoff explicit. A/B benchmark against the fast-copy-only parent on the same host, each side run twice: - CombinedControl U55 lowering: 124.343s / 126.491s with this change vs 148.465s / 149.726s in the parent. Warm speedup: 15.5%; two-run mean speedup: 15.9%. - Synthetic U55 suite: 80.915s / 80.905s vs 81.238s / 82.371s. The 1.1% mean difference is within run-to-run noise; CombinedControl is the representative workload. Differential Revision: D115374097
4e3427a to
639de3e
Compare
Summary: After ARM pass-skipping and targeted-op ownership landed separately in D106781989, this diff optimizes the remaining `ExportPass` replay cost for passes that declare `target_ops` or `targeted_ops`. Cold operator nodes are copied with `graph.node_copy` instead of being re-dispatched through FakeTensor. Old-to-new node remapping preserves dependencies and `get_attr` values. Fast-copy is disabled when `call()` is overridden, for exact convolution or linear targets, or after a hot node changes nested tensor metadata. The fast path preflights every input before mutating the new graph or module tree, so a remapping fallback cannot leave orphaned nodes, attributes, or remap entries. An explicitly empty `targeted_ops` remains authoritative instead of falling back to legacy `target_ops`. Nested ARM control-flow submodules use the established `ArmPass.should_run_pass()` contract. This diff does not duplicate pass auto-discovery or generic skipping logic owned by D106781989. Per review from `jrstevens`, the process-global FakeTensor cache extension is now isolated in child D115374097 so its monkeypatching design and incremental performance can be reviewed independently. A/B benchmark against the parent revision on the same host, each side run twice: - CombinedControl U55 lowering: 148.465s / 149.726s with fast-copy vs 165.886s / 171.181s before it. Warm speedup: 12.5%; two-run mean speedup: 11.5%. - Synthetic U55 suite: 81.238s / 82.371s vs 83.816s / 80.802s. The difference is within run-to-run noise; the large model is the representative workload. Differential Revision: D97528110
…#21700) Summary: Split from D97528110 so the FakeTensor cache extension can be reviewed independently from cold-node fast-copy. `FakeTensorMode` normally caches only `aten`, `prim`, and `prims` operations. ExportPass replay repeatedly dispatches deterministic backend operators from `quantized_decomposed`, `tosa`, and `cortex_m`, but PyTorch stores `non-builtin` negative cache entries for them. This change temporarily extends `torch._library.utils.is_builtin` while ExportPass runs, evicts only matching `non-builtin` bypass entries from the class-global and active ShapeEnv caches, and restores the exact original predicate in `finally`. Positive entries remain available across successive passes, which is the source of the speedup. This intentionally remains a narrow process-global monkeypatch. Current `FakeTensorMode` has no per-instance cache-policy hook, and its non-symbolic cache is class-global. The reentrant lock serializes participating ExportPass contexts, but unrelated threads can observe the extended predicate while the context is active. Fully isolated behavior requires an upstream policy hook plus cache-policy identity or per-mode cache storage; keeping this in a separate diff makes that tradeoff explicit. A/B benchmark against the fast-copy-only parent on the same host, each side run twice: - CombinedControl U55 lowering: 124.343s / 126.491s with this change vs 148.465s / 149.726s in the parent. Warm speedup: 15.5%; two-run mean speedup: 15.9%. - Synthetic U55 suite: 80.915s / 80.905s vs 81.238s / 82.371s. The 1.1% mean difference is within run-to-run noise; CombinedControl is the representative workload. Differential Revision: D115374097
639de3e to
173c7bd
Compare
|
Hold on any reviewing here. There iis a way to do this without any monkeypatching, but it requires an extension to torch itself. That diff is written, will be submitted RFC to torch. |
Summary:
Split from D97528110 so the FakeTensor cache extension can be reviewed independently from cold-node fast-copy.
FakeTensorModenormally caches onlyaten,prim, andprimsoperations. ExportPass replay repeatedly dispatches deterministic backend operators fromquantized_decomposed,tosa, andcortex_m, but PyTorch storesnon-builtinnegative cache entries for them. This change temporarily extendstorch._library.utils.is_builtinwhile ExportPass runs, evicts only matchingnon-builtinbypass entries from the class-global and active ShapeEnv caches, and restores the exact original predicate infinally. Positive entries remain available across successive passes, which is the source of the speedup.This intentionally remains a narrow process-global monkeypatch. Current
FakeTensorModehas no per-instance cache-policy hook, and its non-symbolic cache is class-global. The reentrant lock serializes participating ExportPass contexts, but unrelated threads can observe the extended predicate while the context is active. Fully isolated behavior requires an upstream policy hook plus cache-policy identity or per-mode cache storage; keeping this in a separate diff makes that tradeoff explicit.A/B benchmark against the fast-copy-only parent on the same host, each side run twice:
Differential Revision: D115374097