Skip to content

[PyTorch] Grouped MLP: emit FP32 scale gradient with no cast to BF16 - #3870

Open
sraman-rgb wants to merge 11 commits into
NVIDIA:mainfrom
sraman-rgb:sraman/grouped-mlp-fp32-scales-grad
Open

sraman-rgb wants to merge 11 commits into
NVIDIA:mainfrom
sraman-rgb:sraman/grouped-mlp-fp32-scales-grad

Conversation

@sraman-rgb

@sraman-rgb sraman-rgb commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

The block-scaled fused grouped MLP backward rounds the FP32 scale (router probability) gradient to the compute dtype with .to(dtype). When the scales input is FP32 (e.g. FP32 dispatched router probabilities), autograd then casts that BF16 gradient back to FP32: two cast kernels per layer and microbatch.

Description

Please include a brief summary of the changes, relevant motivation and context.

Fixes # (issue)

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

Please list the changes introduced in this PR:

  • Change A
  • Change B

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

…2 scales

The block-scaled fused grouped MLP backward rounds the FP32 scale (router
probability) gradient to the compute dtype with `.to(dtype)`. When the scales
input is FP32 (e.g. FP32 dispatched router probabilities), autograd then casts
that BF16 gradient back to FP32: two cast kernels per layer and microbatch.

Return float32(round(grad, compute dtype)) directly from one Triton kernel
(`round_through_dtype`) when the scales are FP32. The values are bitwise
identical to the previous `.to(bf16)` + autograd `.to(fp32)` pair; BF16/FP16
scales keep the old path.

Signed-off-by: Siddhartha Raman S <sraman@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge.

Summary

The grouped MLP keeps FP32 scale gradients without rounding them to BF16 first.

  • Fused grouped MLPs keep FP32 scales and their gradients in FP32.

Both earlier findings are addressed. No new actionable issues were found. GPU tests were not run.

Reviews (9) · Last reviewed commit: "Revert properly" · Reviewed by Greptile

@sraman-rgb sraman-rgb changed the title [PyTorch] Grouped MLP: emit FP32 scale gradient in one kernel for FP3… [PyTorch] Grouped MLP: emit FP32 scale gradient in one kernel for FP32 scales Nov 13, 2026
sraman-rgb and others added 3 commits November 13, 2026 12:15
Review feedback: the block-scaled fused grouped MLP rounded the FP32 scale (router
probability) gradient from the cuDNN kernels to the compute dtype with .to(dtype), a
leftover from when the scales were always BF16. With FP32 scales, autograd then cast it back
to FP32, so the gradient lost precision for no reason and cost two cast kernels.

Return the gradient in the dtype of the scales input instead, as the BF16 fused grouped MLP
path already does: FP32 scales get the kernels' FP32 values unchanged (no cast), BF16 scales
get one cast as before. This drops the round_through_dtype Triton kernel. The test checks the
FP32 gradient is returned bitwise unchanged with no cast in the backward, and the BF16 case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Siddhartha Raman S <sraman@nvidia.com>
…casts

Review feedback: the scale gradient from the cuDNN kernels is already FP32, so return it as is
(no helper; autograd casts it for lower-precision scales), and pass the scales to the cuDNN
kernels in FP32 in the forward for every recipe, as the NVFP4 path already did, instead of
rounding them to the compute dtype for MXFP8. Drops the cast-counting test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Siddhartha Raman S <sraman@nvidia.com>
vthumbe1503
vthumbe1503 previously approved these changes Nov 14, 2026

@vthumbe1503 vthumbe1503 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@vthumbe1503

Copy link
Copy Markdown
Collaborator

/te-ci pytorch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Siddhartha Raman S <sraman@nvidia.com>
ksivaman
ksivaman previously approved these changes Nov 14, 2026

@ksivaman ksivaman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@sraman-rgb
sraman-rgb dismissed stale reviews from ksivaman and vthumbe1503 via 7dc8e0c November 14, 2026 02:57
@sraman-rgb sraman-rgb changed the title [PyTorch] Grouped MLP: emit FP32 scale gradient in one kernel for FP32 scales [PyTorch] Grouped MLP: emit FP32 scale gradient with no cast to BF16 Nov 14, 2026
vthumbe1503
vthumbe1503 previously approved these changes Nov 14, 2026
@vthumbe1503

Copy link
Copy Markdown
Collaborator

/te-ci pytorch

Signed-off-by: vthumbe1503 <vthumbe@nvidia.com>
pre-commit-ci Bot and others added 2 commits November 14, 2026 04:49
Signed-off-by: vthumbe1503 <vthumbe@nvidia.com>
Ensure fc1_prob_tensor is converted to fp32 only when using NVFP4.

Signed-off-by: vthumbe1503 <vthumbe@nvidia.com>
@vthumbe1503

Copy link
Copy Markdown
Collaborator

/te-ci pytorch

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants