Skip to content

MxFP8 gradient cross entropy option - #3758

Open
sraman-rgb wants to merge 9 commits into
NVIDIA:mainfrom
sraman-rgb:sraman/te-ce-mxfp8-grad
Open

sraman-rgb wants to merge 9 commits into
NVIDIA:mainfrom
sraman-rgb:sraman/te-ce-mxfp8-grad

Conversation

@sraman-rgb

Copy link
Copy Markdown
Collaborator

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

sraman-rgb and others added 2 commits October 27, 2026 12:36
… launch

Add a grad_quantizer argument to parallel_cross_entropy. With an
MXFP8Quantizer (E4M3 or E5M2, compact scales), a BF16 input on a single
rank, and row count and vocabulary that are multiples of 128, one Triton
kernel writes the derivative as an MXFP8 tensor with row-wise and
column-wise data, bit-identical to quantizing the BF16 derivative with the
quantizer. A following MXFP8 linear layer (an LM head) then skips its own
grad-output quantization pass. Other cases compute the derivative as
before and quantize it.

Launch the single-rank forward with 4096-element blocks and 4 warps and the
backward with 4096-element blocks and 8 warps instead of one 32-warp
program with up to 32K elements per row, and find the argmax with a
min-reduction over the block maximum instead of tl.max(return_indices=True).
Only the accumulation order of the softmax statistics changes.

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

The NaN/Inf selects in the E8M0 exponent and reciprocal helpers slowed the
fused MXFP8 backward from about 340 us to 420 us at 4096 x 129280 on a Rubin
GPU. Finite gradients, the only ones a training step uses, still get the
bytes of TE's MXFP8 cast; this is now stated in the docstring.

Signed-off-by: Siddhartha Raman S <sraman@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sraman-rgb
sraman-rgb requested a review from ksivaman as a code owner October 27, 2026 20:45
@ksivaman ksivaman self-assigned this Oct 27, 2026
@greptile-apps

greptile-apps Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no new actionable issues remain.

Summary

Adds optional quantized gradients to parallel_cross_entropy, including a fused MXFP8 backward path for supported BF16 shapes.

  • Cross entropy handles masked logits without breaking its softmax.
  • Cross entropy can return its logits gradient in MXFP8.

No new actionable issues found. Tests were not run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Backward] --> B{grad_quantizer supplied?}
    B -->|No| C[Existing gradient kernel]
    B -->|Yes| D{Supported MXFP8 configuration?}
    D -->|Yes| E[Fused gradient and MXFP8 kernel]
    D -->|No| F[Existing gradient kernel]
    F --> G[Quantize gradient]
Loading

Reviews (7) · Last reviewed commit: "Small testing refactors" · Reviewed by Greptile

sraman-rgb and others added 5 commits November 11, 2026 11:04
…sum into NaN

When every logit seen so far in a row is -inf, the online softmax shifted
the exponentials by a running maximum of -inf, so exp(-inf - (-inf)) made
the sum of exponentials NaN for the rest of the row. With 4096-wide forward
blocks this happens for any row whose first block is masked. Shift by 0
until a finite maximum is seen, in the single-rank and tensor-parallel
forward kernels and in the cross-rank merge. Rows with a finite maximum
compute exactly as before; rows whose logits are all -inf still give NaN,
as in PyTorch.

Add tests with masked logits against PyTorch, including the MXFP8 gradient,
CUDA graph replay and tensor parallelism.

Signed-off-by: Siddhartha Raman S <sraman@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
Resolve conflicts with the upstream NaN fix (e41b2be): keep its _safe_shift
kernels and masked-logits tests, which supersede the equivalent changes on
ksivamani/nan_fix. Keep from ksivamani/nan_fix the tensor-parallel fused MXFP8
backward, the removal of the dead contiguity check, the fused-kernel launch
checks, the 128-column tile coverage and the tensor-parallel MXFP8 test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
Signed-off-by: Kirthi Shankar Sivamani <ksivamani@nvidia.com>
@ksivaman

Copy link
Copy Markdown
Member

/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.

2 participants