Prototype NVFP4 with FP8 UE5M3 block scales - #3325
Open
timmoon10 wants to merge 57 commits into
Open
Conversation
Co-authored-by: Teddy Do <tdophung@nvidia.com> Co-authored-by: Varun Thumbe <vthumbe@nvidia.com> Signed-off-by: Tim Moon <tmoon@nvidia.com>
for more information, see https://pre-commit.ci
This comment was marked as outdated.
This comment was marked as outdated.
13 tasks
* [PyTorch] Enable e5m3 fused GEMM kernels from cuDNN Signed-off-by: Kaining Zhong <kainingz@nvidia.com> * have to pad to 256 to use cuDNN Signed-off-by: Kaining Zhong <kainingz@nvidia.com> * fix: need to pass scale_dtype Signed-off-by: Kaining Zhong <kainingz@nvidia.com> * route wgrad to cuDNN's wgrad API Signed-off-by: Kaining Zhong <kainingz@nvidia.com> * Support grouped linear with NVFP4-UE5M3 NVFP4-UE5M3 grouped GEMM falls back to dense GEMMs. Generalize usage of wgrad kernel and use when tensors sizes are not 256-aligned. Fix inconsistent m,n,k GEMM notation. Remove ue5m3 hacks in op fuser tests. Add ue5m3 to grouped MLP tests. Signed-off-by: Tim Moon <tmoon@nvidia.com> * Fix typos Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Tim Moon <tmoon@nvidia.com> --------- Signed-off-by: Kaining Zhong <kainingz@nvidia.com> Signed-off-by: Tim Moon <tmoon@nvidia.com> Co-authored-by: Tim Moon <tmoon@nvidia.com> Co-authored-by: Codex <noreply@openai.com>
kainzhong
reviewed
Aug 13, 2026
timmoon10
commented
Aug 13, 2026
Signed-off-by: Tim Moon <tmoon@nvidia.com>
Signed-off-by: Tim Moon <tmoon@nvidia.com>
timmoon10
force-pushed
the
nvfp4-ue5m3-prototype
branch
from
August 14, 2026 12:09
0987860 to
ab3a9b3
Compare
for more information, see https://pre-commit.ci
timmoon10
commented
Aug 14, 2026
Signed-off-by: Tim Moon <tmoon@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Tim Moon <tmoon@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Tim Moon <tmoon@nvidia.com>
timmoon10
marked this pull request as ready for review
August 17, 2026 21:35
timmoon10
requested review from
Oleg-Goncharov,
ksivaman and
ptrendx
as code owners
August 17, 2026 21:35
Contributor
Greptile SummaryThe PR prototypes NVFP4 tensors with FP8 UE5M3 block scales across native quantization, GEMM integration, PyTorch/JAX bindings, recipes, storage, and tests.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains in the previously reviewed paths. No blocking failure remains. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
R[NVFP4 recipe with UE5M3 scales] --> Q[Framework quantizer]
Q --> T[NVFP4 tensor and grouped storage]
T --> B[PyTorch or JAX native bindings]
B --> K[Quantize and dequantize kernels]
B --> G[cuDNN frontend GEMM kernels]
K --> O[Encoded FP4 values and UE5M3 scales]
G --> O
O --> V[Exact and integration tests]
Reviews (30): Last reviewed commit: "[pre-commit.ci] auto fixes from pre-comm..." | Re-trigger Greptile |
Signed-off-by: Tim Moon <tmoon@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Tim Moon <tmoon@nvidia.com>
timmoon10
force-pushed
the
nvfp4-ue5m3-prototype
branch
from
August 28, 2026 08:54
98792fe to
93cbd0a
Compare
for more information, see https://pre-commit.ci
Signed-off-by: Tim Moon <tmoon@nvidia.com>
Member
Author
|
/te-ci L1 |
Signed-off-by: Tim Moon <tmoon@nvidia.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Tim Moon <tmoon@nvidia.com>
Member
Author
|
/te-ci L1 |
…ard compatibility Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Tim Moon <tmoon@nvidia.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Tim Moon <tmoon@nvidia.com>
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Tim Moon <tmoon@nvidia.com>
for more information, see https://pre-commit.ci
Member
Author
|
/te-ci L1 |
* Make NVFP4-UE5M3 grouped GEMM CUDA-graph safe
The UE5M3 grouped GEMM builds its one-element int32 offsets tensor inline
at two call sites:
torch.tensor([tokens], dtype=torch.int32, device=a_tensor.device) # wgrad
torch.tensor([N], dtype=torch.int32, device=device) # fprop
Each of these materializes an unpinned CPU tensor and copies it host-to-device.
CUDA rejects that during graph capture:
RuntimeError: Cannot copy between CPU and CUDA tensors during CUDA graph
capture unless the CPU tensor is pinned. Please use tensor.pin_memory() or
allocate the tensor with pin_memory=True.
Any model capturing these GEMMs in a CUDA graph therefore fails at capture
time. This was hit end-to-end on DeepSeek-V3 671B, where every convergence
config captures full forward/backward graphs; it aborts during warmup capture
and no training step completes.
Route both sites through a cached helper, mirroring get_cached_ones_tensor in
this same file -- which both functions already use for their `ones` tensor a
few lines earlier, and whose docstring notes it keeps "stable data pointers
across CUDA graph replays". Caching by (value, device) moves the host-to-device
copy to warmup and keeps the pointer stable across replays.
The offsets are constant for a given shape, so this is numerically neutral.
Signed-off-by: Michal Futrega <mfutrega@nvidia.com>
* Review suggestions
Co-authored-by: Tim Moon <4406448+timmoon10@users.noreply.github.com>
Signed-off-by: Tim Moon <4406448+timmoon10@users.noreply.github.com>
---------
Signed-off-by: Michal Futrega <mfutrega@nvidia.com>
Signed-off-by: Tim Moon <4406448+timmoon10@users.noreply.github.com>
Co-authored-by: Tim Moon <4406448+timmoon10@users.noreply.github.com>
tdophung
reviewed
Sep 1, 2026
Collaborator
|
/te-ci L1 |
b3415c1 gated the NVFP4 per-tensor scale branch in cublas_gemm() on have_nvfp4_amax, an OR over the two operands' amax pointers. That branch is also what moves alpha/beta from host into device workspace, and CUBLASLT_POINTER_MODE_DEVICE is set unconditionally for every NVFP4 GEMM. So when both operands had a null amax the branch was skipped, leaving alpha/beta as host stack pointers that cuBLAS then dereferenced as device addresses -- garbage output, not a mis-scaled result. That is exactly the shape of the CI failure: only the both_unit_global_scale parametrization of test_gemm_with_missing_nvfp4_amax went red, while the x_/w_ cases passed because the OR still held. Note that nvte_nvfp4_compute_per_tensor_scale with a null amax is an exact identity on alpha (it substitutes scale_max * fp4_max), so skipping it never saved meaningful work -- its real job on that path is materializing the scalars on device. Making the call is always safe; skipping it is not. Replace the heuristic with kNVTEMatmulConfigAlphaBetaOnDevice, which states pointer residency directly instead of inferring it. Default false, so PyTorch (nvte_cublas_gemm/_scaled pass host pointers, and generic_gemm reaches nvte_cublas_gemm_v2 without setting the flag) is restored to its pre-b3415c19 behavior. JAX sets it when is_nvfp4_scaling(), matching the device buffers it binds for alpha/beta, and folds the per-tensor scale into alpha itself. Also document in the JAX helper that its block-scale bound is hardcoded to E4M3's 448 while the C++ get_nvfp4_scale_max() returns 114688 for UE5M3, which will need reconciling once UE5M3 reaches the JAX path. Verified on GB200: tests/pytorch/nvfp4 9310 passed / 0 failed / 6852 skipped (CI at b3415c1 was 9309 passed / 1 failed / 6852 skipped), tests/pytorch/mxfp8 371 passed, and JAX nvfp4+gemm 382 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collaborator
|
/te-ci L1 |
timmoon10
commented
Sep 2, 2026
Co-authored-by: Tim Moon <4406448+timmoon10@users.noreply.github.com> Signed-off-by: Tim Moon <4406448+timmoon10@users.noreply.github.com>
…EMM (#5) * Do not swizzle operand scales in place in the NVFP4-UE5M3 GEMM The cuDNN UE5M3 GEMM wrapper swizzled A/B scales in place and marked the tensors as swizzled. For weights that mark persisted on the parameter. The master-weight cast (_cast_master_weights_to_nvfp4_2d, used by Megatron's fp4 param gather after every optimizer step) then rewrote the scales in the unswizzled layout without clearing the mark, so every later GEMM and dequantize read unswizzled scales as swizzled. Gaussian weights hide it (near-uniform scales, ~0.2 relative error); real DeepSeek-V3 weights are destroyed (2.6 relative error, loss 12.98 vs 7.86 for E4M3 under identical routing). Swizzle clones of the scale tensors instead and leave the operands untouched, matching what the cuBLAS path does in C++. * Test that the NVFP4-UE5M3 GEMM leaves operand scales untouched * Avoid suppressing errors in swizzle function. Signed-off-by: Tim Moon <4406448+timmoon10@users.noreply.github.com> --------- Signed-off-by: Tim Moon <4406448+timmoon10@users.noreply.github.com> Co-authored-by: Tim Moon <4406448+timmoon10@users.noreply.github.com>
Member
Author
|
/te-ci L1 |
for more information, see https://pre-commit.ci
jberchtold-nvidia
approved these changes
Sep 2, 2026
jberchtold-nvidia
left a comment
Collaborator
There was a problem hiding this comment.
Approving for code owner permissions for the two TE/JAX files. Thanks!
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.
Description
This is a proof-of-concept for NVFP4 with FP8 UE5M3 block scales. Quantization is supported natively and GEMMs go through the cuDNN Frontend kernels (see NVIDIA/cudnn-frontend#545).
Type of change
Changes
Checklist: