sgl-project--sglang
94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
137 行
5.4 KiB
Python
137 行
5.4 KiB
Python
"""Unit tests for the row-padded quant path of the cutlass FP8 blockwise linear.
|
|
|
|
`cutlass_w8a8_block_fp8_linear_with_fallback` quantizes activations into
|
|
row-aligned buffers (`sglang_per_token_group_quant_fp8_row_padded`) so the
|
|
`fp8_blockwise_scaled_mm` wrapper's per-call mat_a/scales_a padding short-
|
|
circuits. These tests pin the invariant that this is numerically identical to
|
|
the legacy unpadded path, across both row-aligned and unaligned M.
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import torch
|
|
|
|
from sglang.srt.layers.quantization.fp8_kernel import (
|
|
fp8_dtype,
|
|
per_token_group_quant_fp8,
|
|
sglang_per_token_group_quant_fp8_row_padded,
|
|
)
|
|
from sglang.srt.layers.quantization.fp8_utils import (
|
|
_check_cutlass_block_fp8_hardware_support,
|
|
cutlass_w8a8_block_fp8_linear_with_fallback,
|
|
)
|
|
from sglang.test.ci.ci_register import register_cuda_ci
|
|
from sglang.test.test_utils import CustomTestCase
|
|
|
|
register_cuda_ci(est_time=15, stage="base-b", runner_config="1-gpu-large")
|
|
|
|
_FP8_MAX = torch.finfo(fp8_dtype).max
|
|
_BLOCK = 128
|
|
# Cover M == 1 (greedy decode), small unaligned M (speculative draft tokens),
|
|
# the 4-row alignment boundary, and a large aligned batch.
|
|
_M_VALUES = [1, 2, 3, 4, 5, 7, 13, 16, 31, 64, 256]
|
|
|
|
|
|
def _quant_weight_blockwise(weight_bf16: torch.Tensor, block: int = _BLOCK):
|
|
"""Block-quantize a (N, K) bf16 weight to fp8 with (N//block, K//block) fp32 scales."""
|
|
n, k = weight_bf16.shape
|
|
assert n % block == 0 and k % block == 0
|
|
w = weight_bf16.float().reshape(n // block, block, k // block, block)
|
|
amax = w.abs().amax(dim=(1, 3)).clamp(min=1e-12) # (N//block, K//block)
|
|
scale = amax / _FP8_MAX
|
|
wq = (w / scale[:, None, :, None]).clamp(-_FP8_MAX, _FP8_MAX).to(fp8_dtype)
|
|
return wq.reshape(n, k), scale.to(torch.float32)
|
|
|
|
|
|
def _legacy_cutlass_linear(x_2d, weight, weight_scale):
|
|
"""The pre-optimization path: unpadded quant, wrapper pads internally."""
|
|
from sgl_kernel import fp8_blockwise_scaled_mm
|
|
|
|
q_input, x_scale = per_token_group_quant_fp8(x_2d, _BLOCK, column_major_scales=True)
|
|
return fp8_blockwise_scaled_mm(
|
|
q_input, weight.T, x_scale, weight_scale.T, out_dtype=x_2d.dtype
|
|
)
|
|
|
|
|
|
@unittest.skipUnless(
|
|
_check_cutlass_block_fp8_hardware_support(),
|
|
"cutlass block FP8 requires Hopper (SM90) or newer",
|
|
)
|
|
class TestFP8BlockwiseRowPadding(CustomTestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.K = 512
|
|
cls.N = 256
|
|
torch.manual_seed(0)
|
|
|
|
def test_quant_buffers_row_aligned(self):
|
|
"""Row-padded quant returns 4-aligned, M-major buffers whose live rows
|
|
match the legacy column-major quant bit-for-bit."""
|
|
for m in _M_VALUES:
|
|
x = torch.randn(m, self.K, device="cuda", dtype=torch.bfloat16) * 0.1
|
|
xq, xs = sglang_per_token_group_quant_fp8_row_padded(x, _BLOCK)
|
|
m_pad = (m + 3) // 4 * 4
|
|
|
|
self.assertEqual(xq.shape, (m_pad, self.K), f"M={m}")
|
|
self.assertEqual(xs.shape[0], m_pad, f"M={m}")
|
|
# scales_a must stay M-major (stride(0) == 1) for the kernel contract.
|
|
self.assertEqual(xs.stride(0), 1, f"M={m}")
|
|
|
|
xq_ref, xs_ref = per_token_group_quant_fp8(
|
|
x, _BLOCK, column_major_scales=True
|
|
)
|
|
self.assertEqual(xq_ref.shape, (m, self.K), f"M={m}")
|
|
# Live rows are produced by the same kernel, so they must be identical.
|
|
self.assertTrue(
|
|
torch.equal(xq[:m].view(torch.uint8), xq_ref.view(torch.uint8)),
|
|
f"quantized activation mismatch at M={m}",
|
|
)
|
|
torch.testing.assert_close(xs[:m], xs_ref, atol=0.0, rtol=0.0)
|
|
|
|
def test_gemm_bit_exact_vs_legacy(self):
|
|
"""The full linear (row-padded) is bit-identical to the legacy unpadded GEMM."""
|
|
weight_bf16 = (
|
|
torch.randn(self.N, self.K, device="cuda", dtype=torch.bfloat16) * 0.1
|
|
)
|
|
weight, weight_scale = _quant_weight_blockwise(weight_bf16)
|
|
|
|
for m in _M_VALUES:
|
|
x = torch.randn(m, self.K, device="cuda", dtype=torch.bfloat16) * 0.1
|
|
|
|
out_ref = _legacy_cutlass_linear(x, weight, weight_scale)
|
|
out_new = cutlass_w8a8_block_fp8_linear_with_fallback(
|
|
input=x,
|
|
weight=weight,
|
|
block_size=[_BLOCK, _BLOCK],
|
|
weight_scale=weight_scale,
|
|
)
|
|
|
|
self.assertEqual(out_new.shape, (m, self.N), f"M={m}")
|
|
self.assertTrue(
|
|
torch.equal(out_ref, out_new),
|
|
f"row-padded GEMM differs from legacy at M={m}: "
|
|
f"max_abs_diff={(out_ref.float() - out_new.float()).abs().max().item()}",
|
|
)
|
|
|
|
def test_linear_matches_bf16_reference(self):
|
|
"""Sanity: the FP8 linear stays close to a bf16 reference matmul."""
|
|
weight_bf16 = (
|
|
torch.randn(self.N, self.K, device="cuda", dtype=torch.bfloat16) * 0.1
|
|
)
|
|
weight, weight_scale = _quant_weight_blockwise(weight_bf16)
|
|
|
|
for m in [1, 5, 64]:
|
|
x = torch.randn(m, self.K, device="cuda", dtype=torch.bfloat16) * 0.1
|
|
ref = (x.float() @ weight_bf16.float().T).to(torch.bfloat16)
|
|
out = cutlass_w8a8_block_fp8_linear_with_fallback(
|
|
input=x,
|
|
weight=weight,
|
|
block_size=[_BLOCK, _BLOCK],
|
|
weight_scale=weight_scale,
|
|
)
|
|
torch.testing.assert_close(out, ref, atol=0.5, rtol=0.1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|