Repository navigation
Conversation
Unswizzled MXFP8 scale_inv tensors need only one entry per block, and quantize_ accepts compact (unpadded) buffers, but the quantize kernels assumed TE's 128x4-padded layout: - The generic kernel stored rowwise scales for every row of its chunk and colwise scales without any bounds check. It wrote past the end of compact buffers and, when cols is not a multiple of 64, into the next scale row. - The staged bidimensional kernel writes rowwise scales in 4- or 8-byte groups and colwise scales for whole 64-column iterations, so compact rows that are not a multiple of four scales long were dropped or misplaced. - The register-resident kernels use vector stores, which fault on compact views that are not 16-byte aligned. Bound the generic kernel's scale stores by the scale tensor's shape, which leaves TE's padded layout unchanged, and send compact layouts that the specialized kernels cannot store to the generic kernel. Reject unswizzled scale tensors smaller than one scale per block. Fixes NVIDIA#3689 Signed-off-by: zhaoye <772971548@qq.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
XFDG
marked this pull request as ready for review
October 19, 2026 15:32
Contributor
[Medium impact] The PR appears safe to merge; the previous alignment issue is fixed and no new actionable issues were found. SummaryAdds support for compact, unswizzled MXFP8 scale buffers.
The previous alignment finding is fixed. No new actionable issues were found. GPU tests were not run during this review. Reviews (2) · Last reviewed commit: "[Common] Check MXFP8 scale row lengths b..." · Reviewed by Greptile |
…kernel Unswizzled scale_inv tensors whose rows hold more entries than blocks, such as a view into a wider buffer, passed the new layout checks, but two kinds of specialized kernels cannot store into them: - The register-resident bidimensional kernel writes each colwise scale row with 64- or 128-bit stores. A row length that is not a multiple of 16 bytes faults with a misaligned address from the second row on. - The rowwise-only kernels assume packed scale rows. The register-resident one rejects longer rows in its launcher. The staged one returns early from threads past the last column, before its scale flush, which leaves some of the longer rows unwritten. Send rowwise-only casts into longer scale rows to the generic kernel, and colwise scale rows that are not a multiple of 16 bytes long to the staged bidimensional kernel. TE's padded scales and compact scales meet both conditions, so their kernel selection is unchanged. Extend the PyTorch and C++ tests with longer scale rows, FP16 input for the staged rowwise kernel, and a second colwise scale row for the register-resident bidimensional kernel. Signed-off-by: zhaoye <772971548@qq.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
cc @vthumbe1503 FYI, this PR looks a bit vibey but you might want to steer it? |
This branch has not been deployed
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
MXFP8Tensor.quantize_()accepts caller-provided unswizzledscale_invbuffers, including compact ones that hold one scale per block ((rows, cols/32)rowwise,(rows/32, cols)columnwise) instead of TE's 128x4-padded shape. #3518 asks GEMM to accept such scales too (#3519). The quantize kernels, however, assumed the padded layout, so quantizing into compact buffers wrote outside them or produced wrong scales.Reproduced on current
main(eb3c860) on B200: the reporter's script prints256 256instead of0 0. A sweep over 9 shapes × FP32/BF16/FP16 inputs × rowwise/columnwise/both × 1D/2D scaling, plus E5M2, passed 53 of 180 cases. Compact views 1 or 4 bytes past 16-byte alignment raisedcudaErrorMisalignedAddress. The FP8 data was always correct; the scales were wrong in three kernels:quantize_mxfp8_kernelrows % 64 != 0and into the next scale row whencols % 64 != 0.CastTraitsSwizzle)cols % 128 == 0/% 256 == 0So BF16 inputs stay in bounds only for some shapes.
Review of the first commit found that views whose scale rows hold more entries than blocks also fail in the specialized kernels. The register-resident bidimensional kernel faults when columnwise scale rows are not a multiple of 16 bytes long. The rowwise-only kernels reject such rows (register-resident) or leave some of them unwritten (staged).
Fixes #3689
Type of change
Changes
tests/pytorch/mxfp8/test_mxfp8_quantize_compact_scales.pyandCompactScalesCastMXFP8TestSuiteintests/cpp/operator/test_cast_mxfp8.cuquantize into compact views, and into views whose scale rows hold more entries than blocks. Canary bytes surround every view, and the views are aligned and unaligned. The tests compare the results byte for byte with TE's padded output. The C++ suite also covers FP16 input and the dbias variant.GEMM's handling of compact scales (#3519) is unchanged.
Checklist:
Testing on B200 (CUDA 13.1, PyTorch 2.11.0a0)
PyTorch-only editable build for
sm_100awithNVTE_WITH_NCCL_EP=0andNVTE_WITH_CUTEDSL=0. Each run checked that the imported libraries came from this build.main(eb3c860)9cae9e1)256 2560 00 0test_cast_mxfp8tests/pytorch/mxfp8test_mxfp8_2d_quantize.pytest_quantized_tensor.pytest_numerics.py -k mxfp8test_fusible_ops.py -k mxfp8test_weight_swizzle_in_layers.pytest_partial_cast.pyNot covered: JAX (not installed; JAX passes padded MXFP8 scales, which keep the same stores and kernels), the CuTeDSL backend (not built), and performance (not measured).
The C++ operator tests on
maindo not compile with CUDA 13.1. Since #3325,DType::kFloat8UE5M3exists for every CUDA version, butTypeInfo::typeslistsfp8ue5m3only for CUDA 13.4 and later. I builttest_cast_mxfp8.cuagainst a local copy oftest_common.hthat ends the type lookup there; that workaround is not part of this PR.🤖 Generated with Claude Code