main
py 89 lines 3.13 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import torch
5
6 from vllm.logger import init_logger
7 from vllm.model_executor.layers.quantization.utils.humming import (
8 apply_humming_linear,
9 get_humming_linear_compute_config,
10 prepare_humming_linear_layer_config,
11 quant_key_to_input_schema,
12 )
13 from vllm.model_executor.layers.quantization.utils.quant_utils import kNvfp4Dynamic
14 from vllm.platforms import current_platform
15 from vllm.utils.import_utils import has_humming
16
17 from .base import NvFp4LinearKernel, NvFp4LinearLayerConfig
18
19 logger = init_logger(__name__)
20
21
22 class HummingNvFp4LinearKernel(NvFp4LinearKernel):
23 """Humming GEMM Kernel for NVFP4."""
24
25 @classmethod
26 def is_supported(
27 cls, compute_capability: int | None = None
28 ) -> tuple[bool, str | None]:
29 if not current_platform.is_cuda():
30 return False, "Humming only supported on CUDA"
31
32 if not has_humming():
33 return False, "Humming is not installed"
34
35 if not current_platform.has_device_capability(75):
36 return False, "Humming only supported on SM75+"
37
38 return True, None
39
40 @classmethod
41 def can_implement(cls, config: NvFp4LinearLayerConfig) -> tuple[bool, str | None]:
42 return True, None
43
44 def process_weights_after_loading(self, layer: torch.nn.Module) -> None:
45 # Reuse the CT loader for packed FP4 weights and tensor scales.
46 quant_config = {
47 "quant_method": "compressed-tensors",
48 "format": "nvfp4-pack-quantized",
49 "type": "float",
50 "num_bits": 4,
51 "strategy": "group",
52 "group_size": 16,
53 }
54 # CT pack-quantized reads `weight_packed`; the scheme renamed it to `weight`.
55 if not hasattr(layer, "weight_packed"):
56 layer.weight_packed = layer.weight
57 del layer.weight
58 # The CT linear scheme inverts the global scale (1/scale) for
59 # marlin/cutlass; humming wants the original.
60 layer.weight_global_scale = torch.nn.Parameter(
61 1.0 / layer.weight_global_scale, requires_grad=False
62 )
63 input_quant_key = None
64 if hasattr(layer, "input_global_scale"):
65 layer.input_scale_2 = torch.nn.Parameter(
66 layer.input_global_scale.reshape(-1), requires_grad=False
67 )
68 input_quant_key = kNvfp4Dynamic
69 input_schema = quant_key_to_input_schema(input_quant_key)
70 self.layer_config = prepare_humming_linear_layer_config(
71 layer, quant_config, input_schema=input_schema
72 )
73 self.compute_config = get_humming_linear_compute_config()
74 self.locks = torch.zeros(1024, dtype=torch.int32, device=layer.weight.device)
75
76 def apply_weights(
77 self,
78 layer: torch.nn.Module,
79 x: torch.Tensor,
80 bias: torch.Tensor | None = None,
81 ) -> torch.Tensor:
82 return apply_humming_linear(
83 layer,
84 x,
85 skip_bias_add=bias is None,
86 layer_config=self.layer_config,
87 compute_config=self.compute_config,
88 locks=self.locks,
89 )