From f87b8eab23e49fada0aab5488ff94942b35b8979 Mon Sep 17 00:00:00 2001 From: fzyzcjy <5236035+fzyzcjy@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:45:27 +0800 Subject: [PATCH] Tiny fix transform_scale_ue8m0 wrong output in some scenarios (#14003) --- .../srt/layers/quantization/fp8_utils.py | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/python/sglang/srt/layers/quantization/fp8_utils.py b/python/sglang/srt/layers/quantization/fp8_utils.py index 5ad8b502d..f8a98e98f 100644 --- a/python/sglang/srt/layers/quantization/fp8_utils.py +++ b/python/sglang/srt/layers/quantization/fp8_utils.py @@ -575,21 +575,59 @@ def transform_scale_ue8m0_inplace(param, mn): # NOTE copy and modified from DeepGEMM -def transform_scale_ue8m0(sf, mn): +def transform_scale_ue8m0(sf, mn, use_torch_impl: bool = False): import deep_gemm.utils.layout + get_mn_major_tma_aligned_packed_ue8m0_tensor = ( + _get_mn_major_tma_aligned_packed_ue8m0_tensor_torch_impl + if use_torch_impl + else deep_gemm.utils.layout.get_mn_major_tma_aligned_packed_ue8m0_tensor + ) + sf = sf.index_select(-2, torch.arange(mn, device=sf.device) // 128) - sf = deep_gemm.utils.layout.get_mn_major_tma_aligned_packed_ue8m0_tensor(sf) + sf = get_mn_major_tma_aligned_packed_ue8m0_tensor(sf) return sf +# Copied from DeepGEMM tests +def _get_mn_major_tma_aligned_packed_ue8m0_tensor_torch_impl( + x: torch.Tensor, +) -> torch.Tensor: + from deep_gemm.utils import align, get_tma_aligned_size + + assert x.dtype == torch.float and x.dim() in (2, 3) + + # First, convert into UE8M0 `uint8_t` + ue8m0_tensor = (x.view(torch.int) >> 23).to(torch.uint8) + + # Second, make padded packed tensors + mn, k = x.shape[-2], x.shape[-1] + remove_dim = False + if x.dim() == 2: + x, remove_dim = x.unsqueeze(0), True + b = x.shape[0] + aligned_mn = get_tma_aligned_size(mn, 4) + aligned_k = align(k, 4) + padded = torch.zeros((b, aligned_mn, aligned_k), device=x.device, dtype=torch.uint8) + padded[:, :mn, :k] = ue8m0_tensor + padded = padded.view(-1).view(dtype=torch.int).view(b, aligned_mn, aligned_k // 4) + + # Finally, transpose + transposed = torch.zeros( + (b, aligned_k // 4, aligned_mn), device=x.device, dtype=torch.int + ).mT + transposed[:, :, :] = padded + aligned_x = transposed[:, :mn, :] + return aligned_x.squeeze(0) if remove_dim else aligned_x + + def inverse_transform_scale_ue8m0(sf_packed, mn): sf_fp32 = _inverse_transform_scale_ue8m0_impl(sf_packed) # Can call consistency check every time since this is only called on startup - sf_packed_recreated = transform_scale_ue8m0(sf_fp32, mn=mn) + sf_packed_recreated = transform_scale_ue8m0(sf_fp32, mn=mn, use_torch_impl=True) assert torch.all( sf_packed == sf_packed_recreated - ), f"{sf_packed=} {sf_packed_recreated}" + ), f"{sf_packed=} {sf_packed_recreated=} {sf_fp32=}" return sf_fp32