Skip to content

Fix MPS fused RMSNorm: do the weight multiply in fp32 to match CPU/CUDA#189617

Open
Incheonkirin wants to merge 2 commits into
pytorch:mainfrom
Incheonkirin:fix-mps-rmsnorm-fp32-weight-multiply
Open

Fix MPS fused RMSNorm: do the weight multiply in fp32 to match CPU/CUDA#189617
Incheonkirin wants to merge 2 commits into
pytorch:mainfrom
Incheonkirin:fix-mps-rmsnorm-fp32-weight-multiply

Conversation

@Incheonkirin

Copy link
Copy Markdown

This replaces #187779, which I accidentally closed when its source fork was detached. The reviewed patch is unchanged, rebased onto current main, and the original discussion remains in #187779. That PR was approved by the MPS reviewer and completed 113 successful checks with no failures.

What does this PR do?

The MPS fused RMSNorm kernel casts the normalized value to the half dtype before multiplying by the weight (out = w * static_cast<T>(x * inv)), so its output diverges from PyTorch's CPU composite and CUDA fused/reference behavior, which keep the x * inv * weight product in fp32 and cast once at the end (the CPU side was aligned in #147203). This affects half/bfloat16 inference on MPS whenever RMSNorm/rms_norm dispatches to the fused affine kernel (weight present, matching dtype, no grad).

Fix: do the weight multiply in fp32 in the same order as the reference ((x * inv) * weight) and cast once. Adds an MPS regression test that runs the fused kernel in fp16/bf16 and in fp32 with the same inputs (identical reduction) and asserts they agree, so only the weight-multiply precision is checked (N = 4095, 4097, covering both shader paths).

Reproduced on Apple Silicon; the kernel recompile (a full source build) is left to CI.

Validation

@Incheonkirin
Incheonkirin requested a review from malfet as a code owner July 11, 2026 13:51
@pytorch-bot

pytorch-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

❗ 1 Active SEVs

There are 1 currently active SEVs. If your PR is affected, please view them below:

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

@pytorch-bot pytorch-bot Bot added ciflow/mps Run MPS tests (subset of trunk) release notes: mps Release notes category labels Jul 11, 2026
@pytorch-bot

pytorch-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

The following ciflow label(s) have been added but CI has not been triggered yet because the workflows are awaiting approval:

  • ciflow/mps

Once a maintainer approves the workflows (scroll to the bottom of the PR page), the corresponding CI jobs will be triggered automatically. Please ping one of the reviewers if you do not have access to approve and run workflows.

@Incheonkirin

Incheonkirin commented Jul 11, 2026

Copy link
Copy Markdown
Author

@jhavukainen this replaces #187779. I accidentally detached my fork from pytorch's fork network while changing its visibility, which closed that PR and left it un-reopenable from my account. The patch here is line-for-line identical to the one you approved, rebased onto main.

The one adverse check, macos-m2-26, was cancelled by pytorch-bot after 10h55m without ever getting a runner or starting a step; m1-14 and m2-15 passed on the same commit in ~44 min. Could you re-review and approve if it still looks good? A rerun of the cancelled job would help too, if you have the permissions. Thanks.

@albanD albanD added the triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module label Jul 13, 2026
@Incheonkirin

Copy link
Copy Markdown
Author

@jhavukainen gentle re-ping: this is the resubmission of the #187779 patch you approved (identical lines). Could you re-review when you get a chance?

The MPS fused RMSNorm kernel cast the normalized value to the half dtype before
the weight multiply, diverging from the CPU composite and CUDA fused/reference
paths which keep x*inv*weight in fp32 and cast once (CPU aligned in pytorch#147203).
Do the weight multiply in fp32 in the reference order ((x*inv)*weight) and cast
once. Adds an MPS regression test (fp16/bf16, N=4095/4097).
Per review: the four write sites repeated the same upcast, so move it into
one inline helper and use opmath_t<T> instead of hardcoding float (needs
c10/metal/utils.h for opmath_t). No behavior change.
@Incheonkirin
Incheonkirin force-pushed the fix-mps-rmsnorm-fp32-weight-multiply branch from 7b1a34d to fd7d864 Compare July 23, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/mps Run MPS tests (subset of trunk) open source release notes: mps Release notes category triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants