main
py 78 lines 2.43 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 import pytest
4 import torch
5
6 from tests.kernels.quantization.nvfp4_utils import (
7 FLOAT4_E2M1_MAX,
8 FLOAT8_E4M3_MAX,
9 dequantize_nvfp4_to_dtype,
10 )
11 from vllm._custom_ops import scaled_fp4_quant
12 from vllm.model_executor.layers.activation import SiluAndMul
13 from vllm.platforms import current_platform
14 from vllm.utils.torch_utils import set_random_seed
15
16 if not current_platform.has_device_capability(100):
17 pytest.skip(
18 reason="Nvfp4 Requires compute capability of 10 or above.",
19 allow_module_level=True,
20 )
21
22 FP4_DTYPE = torch.uint8
23 FP8_DTYPE = current_platform.fp8_dtype()
24
25 DTYPES = [torch.float16, torch.bfloat16]
26 SHAPES = [(128, 256), (128, 128), (256, 256), (256, 128), (1, 256), (64, 256)]
27 BLOCK_SIZE = 16
28
29
30 @pytest.mark.parametrize("dtype", DTYPES)
31 @pytest.mark.parametrize("shape", SHAPES)
32 @torch.inference_mode()
33 def test_silu_mul_nvfp4_quant(
34 default_vllm_config,
35 dtype: torch.dtype,
36 shape: tuple[int, int],
37 ) -> None:
38 set_random_seed(42)
39 device = "cuda:0"
40 torch.set_default_device(device)
41
42 x = torch.randn(shape, dtype=dtype)
43
44 # ref op
45 ref_output = SiluAndMul().forward_native(x)
46 ref_global_scale = (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX) / torch.abs(
47 ref_output
48 ).max().to(torch.float32)
49 ref_output_quant, ref_block_scale = scaled_fp4_quant(ref_output, ref_global_scale)
50
51 # fused op
52 fused_output_quant = torch.empty_like(ref_output_quant)
53 fused_block_scale = torch.empty_like(ref_block_scale)
54 torch.ops._C.silu_and_mul_nvfp4_quant(
55 fused_output_quant, fused_block_scale, x, ref_global_scale
56 )
57
58 # check dtype
59 assert ref_output_quant.dtype == FP4_DTYPE
60 assert fused_output_quant.dtype == FP4_DTYPE
61 assert ref_output_quant.shape == fused_output_quant.shape
62
63 assert ref_block_scale.dtype == FP8_DTYPE
64 assert fused_block_scale.dtype == FP8_DTYPE
65 assert ref_block_scale.shape == fused_block_scale.shape
66
67 # check dequantized output
68 ref_output_dequant = dequantize_nvfp4_to_dtype(
69 ref_output_quant, ref_block_scale, ref_global_scale, dtype, device
70 )
71 fused_output_dequant = dequantize_nvfp4_to_dtype(
72 fused_output_quant, fused_block_scale, ref_global_scale, dtype, device
73 )
74
75 atol, rtol = 3e-1, 3e-1
76 torch.testing.assert_close(
77 ref_output_dequant, fused_output_dequant, atol=atol, rtol=rtol
78 )