Repository navigation
Conversation
Contributor
|
@billmguo has exported this pull request. If you are a Meta employee, you can view the originating Diff in D118714733. |
Summary:
`ParameterTransform.forward` computes
`einsum("dn,...n->...d", parameter_transform, model_parameters)`. With the
transform shaped `[out, in]`, that contraction is exactly `x @ W.T` -- i.e.
`torch.nn.functional.linear(model_parameters, parameter_transform)`.
The two are numerically equivalent (measured bit-identical on CPU float32 across
unbatched and batched inputs), but they lower very differently under
`torch.export`. The einsum survives export as a single `aten.einsum.default`, and
`to_edge` then decomposes it into `unsqueeze -> permute -> bmm -> permute`. Both
permutes are over the `parameter_transform` buffer, which is registered with
`requires_grad=False` and is identical on every invocation -- so an exported model
re-materializes the entire transform matrix twice per frame. For a character with
889 joint parameters and 204 model parameters that is 181,356 elements copied
twice, on every frame, forever.
Spelling it as a linear removes the output permute and both activation reshapes.
It also lets backends that have a fully-connected primitive (XNNPACK, for
instance) match the op and pre-pack the weight once at initialization rather than
transposing it per invocation, since `xnn_define_fully_connected` already wants
the `[out, in]` layout the buffer is stored in.
Measured on an exported production model running on an Android device:
- The block containing this op drops **30.4%** (4.50 ms -> 3.13 ms per
invocation). Within it, permute time goes 1.86 ms -> 0.61 ms and the `bmm` is
replaced by an equivalently-priced `mm`, so the win is entirely the eliminated
data movement.
- End-to-end on the full exported model, **-7.8%**, confirmed with a paired
interleaved A/B in which every measured block favored the change on both the
median and the minimum.
Eager-mode behavior and results are unchanged; this only affects how the module
lowers when exported.
One consequence worth stating for anyone exporting a model that uses this: the
lowered kernel changes (`bmm` -> `mm` / fully-connected). Eager output is
bit-identical, but two different GEMM paths are not bit-identical to each other,
so a model whose output feeds back into its own next-frame input can accumulate a
small difference over a long rollout. Re-validate such a model's output rather
than assuming exact parity with a previously exported artifact.
Reviewed By: nickyhe-gemini, cdtwigg
Differential Revision: D118714733
billmguo
force-pushed
the
export-D118714733
branch
from
September 4, 2026 00:33
230199b to
2127878
Compare
Contributor
|
This pull request has been merged in 8e7451b. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
ParameterTransform.forwardcomputeseinsum("dn,...n->...d", parameter_transform, model_parameters). With thetransform shaped
[out, in], that contraction is exactlyx @ W.T-- i.e.torch.nn.functional.linear(model_parameters, parameter_transform).The two are numerically equivalent (measured bit-identical on CPU float32 across
unbatched and batched inputs), but they lower very differently under
torch.export. The einsum survives export as a singleaten.einsum.default, andto_edgethen decomposes it intounsqueeze -> permute -> bmm -> permute. Bothpermutes are over the
parameter_transformbuffer, which is registered withrequires_grad=Falseand is identical on every invocation -- so an exported modelre-materializes the entire transform matrix twice per frame. For a character with
889 joint parameters and 204 model parameters that is 181,356 elements copied
twice, on every frame, forever.
Spelling it as a linear removes the output permute and both activation reshapes.
It also lets backends that have a fully-connected primitive (XNNPACK, for
instance) match the op and pre-pack the weight once at initialization rather than
transposing it per invocation, since
xnn_define_fully_connectedalready wantsthe
[out, in]layout the buffer is stored in.Measured on an exported production model running on an Android device:
invocation). Within it, permute time goes 1.86 ms -> 0.61 ms and the
bmmisreplaced by an equivalently-priced
mm, so the win is entirely the eliminateddata movement.
interleaved A/B in which every measured block favored the change on both the
median and the minimum.
Eager-mode behavior and results are unchanged; this only affects how the module
lowers when exported.
One consequence worth stating for anyone exporting a model that uses this: the
lowered kernel changes (
bmm->mm/ fully-connected). Eager output isbit-identical, but two different GEMM paths are not bit-identical to each other,
so a model whose output feeds back into its own next-frame input can accumulate a
small difference over a long rollout. Re-validate such a model's output rather
than assuming exact parity with a previously exported artifact.
Reviewed By: nickyhe-gemini, cdtwigg
Differential Revision: D118714733