Skip to content

Vulkan: implement instance norm by rewriting it to group norm - #22783

Open
msluszniak wants to merge 1 commit into
pytorch:mainfrom
msluszniak:ms/vulkan-instance-norm
Open

Vulkan: implement instance norm by rewriting it to group norm#22783
msluszniak wants to merge 1 commit into
pytorch:mainfrom
msluszniak:ms/vulkan-instance-norm

Conversation

@msluszniak

@msluszniak msluszniak commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

aten._native_batch_norm_legit.no_stats has no Vulkan implementation, so every nn.InstanceNorm2d is a graph break. Architectures that normalize in each block pay for that repeatedly: the fast neural style TransformerNet at 640x640 splits into 16 delegate subgraphs with 126 nodes left on the CPU, and copies its activations out to the CPU and back 15 times per inference.

F.instance_norm reshapes its input to [1, N*C, H, W] before lowering to this overload, so with a batch dim of 1 it is the same reduction as group norm with one group per channel. ReplaceInstanceNormPass rewrites it that way, which the existing group norm kernels already cover, so no new shader is needed. A batch dim above 1 is a different reduction and is left alone.

add_native_group_norm_node() prepacks weight and bias, so the pass only fires when both trace back to a constant. Identity aten.repeat now folds away as well: F.instance_norm emits weight.repeat(b), which would otherwise leave the affine params as runtime tensors that group norm cannot prepack.

Measured on a Mali-G76 (Galaxy S10+), style transfer at 640x640, fp16, per-exec slope interleaved over 3 rounds on a warm device:

median range
before 2265.1 ms 2119.9-2268.4
after 1469.4 ms 1439.6-1480.9

1.54x, non-overlapping. The partition goes from 16 subgraphs to 1 and from 126 CPU nodes to 0.

Accuracy against the fp32 reference improves slightly, cosine 0.999993 -> 0.999994 and max abs diff 0.041 -> 0.031, because the fp16 round trips at the delegate boundaries are gone.

cc @SS-JIA @manuelcandales @digantdesai @cbilgin

`aten._native_batch_norm_legit.no_stats` has no Vulkan implementation, so every
`nn.InstanceNorm2d` is a graph break. Architectures that normalize in each block
pay for that repeatedly: the fast neural style TransformerNet at 640x640 splits
into 16 delegate subgraphs with 126 nodes left on the CPU, and copies its
activations out to the CPU and back 15 times per inference.

`F.instance_norm` reshapes its input to [1, N*C, H, W] before lowering to this
overload, so with a batch dim of 1 it is the same reduction as group norm with
one group per channel. ReplaceInstanceNormPass rewrites it that way and the
existing group norm kernels cover it, so no new shader is needed. A batch dim
above 1 is a different reduction and is left alone.

add_native_group_norm_node() prepacks weight and bias, so the pass only fires
when both trace back to a constant. Identity `aten.repeat` (every repeat factor
1, which the existing shape equality check implies) now folds away as well:
`F.instance_norm` emits `weight.repeat(b)`, which would otherwise leave the
affine params as runtime tensors that group norm cannot prepack.

Measured on a Mali-G76 (Galaxy S10+), style transfer at 640x640, fp16, per-exec
slope interleaved over 3 rounds on a warm device: 2265.1 ms -> 1469.4 ms median,
a 1.54x speedup, with non-overlapping ranges. The partition goes from 16
subgraphs to 1 and from 126 CPU nodes to 0. Output accuracy against the fp32
reference improves slightly as well, cosine 0.999993 -> 0.999994 and max abs
diff 0.041 -> 0.031, because the fp16 round trips at the delegate boundaries are
gone.
@msluszniak
msluszniak requested a review from SS-JIA as a code owner September 13, 2026 12:51
@pytorch-bot

pytorch-bot Bot commented Sep 13, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

⚠️ 15 Awaiting Approval

As of commit a0c5024 with merge base 14dab10 (image):

AWAITING APPROVAL - The following workflows need approval before CI can run:

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

@pytorch-bot pytorch-bot Bot added the module: vulkan Issues related to the Vulkan delegate and code under backends/vulkan/ label Sep 13, 2026
@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 Sep 13, 2026
@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.

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. module: vulkan Issues related to the Vulkan delegate and code under backends/vulkan/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants