Skip to content

Skip xnn_reshape_runtime when the input shapes have not changed (#24219) - #24219

Open
billmguo wants to merge 1 commit into
pytorch:mainfrom
billmguo:export-D127875036
Open

billmguo wants to merge 1 commit into
pytorch:mainfrom
billmguo:export-D127875036

Conversation

@billmguo

@billmguo billmguo commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

XNNExecutor::prepare_args reshapes every external input and calls xnn_reshape_runtime on every execute, which re-runs each operator's reshape and re-plans memory even when no shape changed. Models built from many small XNNPACK partitions pay this per partition per call. In the Phoenix CARMM body synthesizer (38 XNNPACK delegates), a simpleperf profile of HandBodyReplay puts prepare_args at 7.8% of per-frame CPU, 5.7% of it inside xnn_reshape_runtime, versus 14.3% for the delegates' actual compute.

prepare_args now collects each input's rank and dims and reshapes only when they differ from the last successful reshape (or the runtime was never reshaped). Input shapes are the whole reshape input: the runtime partitions work for the pthreadpool it was created with (xnn_create_runtime_v4), whose size cannot change; UseNThreadsThreadPoolGuard only limits threads per dispatch. This is safe because XNNPACK re-binds every data pointer in xnn_setup_runtime_v2, and when one runtime grows a shared workspace it rebases the value and op-workspace pointers of all runtimes sharing it (runtime.c). Two things captured at reshape are reused across skipped calls: per-thread scratch sized from that fixed pool, and the packed-weights address looked up from the weights cache, whose slots are only appended or cleared on release (XNNWeightsCache.cpp). A failed reshape clears the flag, so the next call reshapes again. Output resizing is unchanged.

Edited in both the xplat and fbcode copies, which are kept byte-identical.

Differential Revision: D127875036

@billmguo
billmguo requested a review from digantdesai as a code owner October 27, 2026 23:08
@pytorch-bot

pytorch-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24219

Note: Links to docs will display an error until the docs builds have been completed.

❌ 1 New Failure

As of commit 0e62872 with merge base 0549e1e (image):

NEW FAILURE - The following job has failed:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 27, 2026
@meta-codesync

meta-codesync Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

@billmguo has exported this pull request. If you are a Meta employee, you can view the originating Diff in D127875036.

@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

…rch#24219)

Summary:

`XNNExecutor::prepare_args` reshapes every external input and calls `xnn_reshape_runtime` on every execute, which re-runs each operator's reshape and re-plans memory even when no shape changed. Models built from many small XNNPACK partitions pay this per partition per call. In the Phoenix CARMM body synthesizer (38 XNNPACK delegates), a simpleperf profile of HandBodyReplay puts `prepare_args` at 7.8% of per-frame CPU, 5.7% of it inside `xnn_reshape_runtime`, versus 14.3% for the delegates' actual compute.

prepare_args now collects each input's rank and dims and reshapes only when they differ from the last successful reshape (or the runtime was never reshaped). Input shapes are the whole reshape input: the runtime partitions work for the pthreadpool it was created with (`xnn_create_runtime_v4`), whose size cannot change; `UseNThreadsThreadPoolGuard` only limits threads per dispatch. This is safe because XNNPACK re-binds every data pointer in `xnn_setup_runtime_v2`, and when one runtime grows a shared workspace it rebases the value and op-workspace pointers of all runtimes sharing it (`runtime.c`). Two things captured at reshape are reused across skipped calls: per-thread scratch sized from that fixed pool, and the packed-weights address looked up from the weights cache, whose slots are only appended or cleared on release (`XNNWeightsCache.cpp`). A failed reshape clears the flag, so the next call reshapes again. Output resizing is unchanged.

Edited in both the xplat and fbcode copies, which are kept byte-identical.

Differential Revision: D127875036
@meta-codesync meta-codesync Bot changed the title Skip xnn_reshape_runtime when the input shapes have not changed Skip xnn_reshape_runtime when the input shapes have not changed (#24219) Oct 28, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant