[BugFix][Quant] Accumulate E5M6 BF16 amax in FP32#16
Open
JayceSu98 wants to merge 1 commit into
Open
Conversation
E5M6 per-token casts use the same scale-selection contract as the FP8/FP4 per-token path: compute a per-token/channel absmax, round the dequant scale when requested, then quantize through the inverse scale. The BF16 input path stored the amax reduction result in a BF16 fragment before computing the E5M6 scale. On H100 with CUDA 13.2 this can underestimate the BF16 row amax for large hidden blocks. The resulting scale is one power-of-two too small when round_sf=True, which changes the packed E5M6 bytes. In the cast-back test this bad forward scale can also overflow BF16 dequantization to inf, making the cosine-style diff report nan. Store the E5M6 amax reduction result in FP32 so scale selection matches the PyTorch reference and is not tied to packed BF16 reduction behavior. The cast-back kernel itself does not need a workaround; its nan failures were downstream of the incorrect forward scale. JayceSu98 <jayce.su@enflame-tech.com> authored and validated this patch. Co-author GitHub: https://github.com/dingsg Verified on H100 (NVIDIA H100 PCIe, sm_90) with CUDA 13.2, PyTorch 2.12.0+cu132, and TileLang 0.1.10+cuda.git23d91c58: the 24 per_token_cast_to_e5m6 byte-mismatch cases and 24 cast_back_e5m6 nan-diff cases passed with pytest -n 2. Co-authored-by: dingsg <shengge.ding@enflame-tech.com>
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.
E5M6 per-token casts use the same scale-selection contract as the FP8/FP4 per-token path: compute a per-token/channel absmax, round the dequant scale when requested, then quantize through the inverse scale. The BF16 input path stored the amax reduction result in a BF16 fragment before computing the E5M6 scale.
On H100 with CUDA 13.2 this can underestimate the BF16 row amax for large hidden blocks. The resulting scale is one power-of-two too small when round_sf=True, which changes the packed E5M6 bytes. In the cast-back test this bad forward scale can also overflow BF16 dequantization to inf, making the cosine-style diff report nan.
Store the E5M6 amax reduction result in FP32 so scale selection matches the PyTorch reference and is not tied to packed BF16 reduction behavior. The cast-back kernel itself does not need a workaround; its nan failures were downstream of the incorrect forward scale.
Verified on H100 (NVIDIA H100 PCIe, sm_90) with CUDA 13.2, PyTorch 2.12.0+cu132, and TileLang 0.1.10+cuda.git23d91c58: the 24 per_token_cast_to_e5m6 byte-mismatch cases and 24 cast_back_e5m6 nan-diff cases passed with pytest -n 2.
JayceSu98 jayce.su@enflame-tech.com authored and validated this patch.
Co-author GitHub: https://github.com/dingsg