首页
/ vLLM 量化实战指南:量化格式全景、硬件兼容矩阵与自定义量化插件扩展机制

vLLM 量化实战指南:量化格式全景、硬件兼容矩阵与自定义量化插件扩展机制

2026-09-06 14:40:19作者:秋泉律Samson

本篇指南基于 vLLM 官方量化文档(docs/features/quantization/README.md),系统讲解 vLLM 支持的量化格式清单、各量化实现与 GPU/CPU 硬件平台的兼容性矩阵,以及通过 @register_quantization_config 注册 Out-of-Tree 自定义量化插件的完整机制。读完本文,你将能够:为部署场景选择正确的量化方法名、判断目标硬件是否支持该量化实现、并在不修改 vLLM 代码库的前提下接入自己的量化方案。

量化在 vLLM 中的定位

量化(Quantization)用模型精度的下降换取更小的显存占用,使大模型能够在更广泛的设备上运行。在 vLLM 中,量化能力集中在 vllm/model_executor/layers/quantization 目录下实现,每个量化格式对应一个 QuantizationConfig 子类,引擎启动时根据模型检查点中的量化配置或用户传入的 --quantization 参数选择对应实现。

官方推荐从 LLM Compressor 入手:它是 vLLM 生态中用于“为部署到 vLLM 而优化模型”的量化库,支持 FP8、INT8、INT4 等多种格式,相关文档见 LLM Compressor 入门

vLLM 支持的量化格式清单

vLLM 当前支持的量化格式(对应各格式的专项文档):

硬件平台兼容性矩阵

不同量化实现依赖特定的自定义 CUDA/CPU 内核,因此其与硬件平台存在明确的兼容关系。下表列出各量化实现在不同硬件上的支持情况(“是”表示支持,“否”表示不支持):

量化实现 Volta Turing Ampere Ada Hopper AMD GPU Intel GPU x86 CPU Arm CPU
AWQ
GPTQ
Marlin (GPTQ/AWQ/FP8/FP4) 是*
llm-compressor INT8 (W8A8)
llm-compressor INT8 (W4A8)
llm-compressor FP8 (W8A8)
bitsandbytes
DeepSpeedFP
GGUF

矩阵中的术语与限制说明:

  • 硬件代际对应 CUDA Compute Capability:Volta 为 SM 7.0,Turing 为 SM 7.5,Ampere 为 SM 8.0/8.6,Ada 为 SM 8.9,Hopper 为 SM 9.0。
  • Marlin 一行中的星号(*)表示 Turing 不支持 Marlin 的 MXFP4 格式。
  • Intel Gaudi 上的全部量化支持已迁移至独立的 vLLM-Gaudi 项目,vLLM 主仓库不再覆盖。
  • Google TPU 上的量化支持情况,需查阅 TPU-Inference 官方文档的推荐模型与功能列表。

需要注意:该兼容性表会随 vLLM 持续演进而变化。要获取最新、最权威的硬件支持信息,应直接参考源码目录 vllm/model_executor/layers/quantization,其中的 get_min_capability() 实现即为每个量化方法对 GPU 算力等级的硬性门槛。

Out-of-Tree 量化插件:注册机制解析

vLLM 支持在不修改主代码库的前提下注册自定义(Out-of-Tree)量化方法,入口是 @register_quantization_config 装饰器。从源码看,这一机制的落点在 vllm/model_executor/layers/quantization/init.py

  1. 装饰器把自定义配置类写入模块级字典 _CUSTOMIZED_METHOD_TO_QUANT_CONFIG,并将其名称追加到 QUANTIZATION_METHODS 列表;
  2. 若当前平台维护了 supported_quantization 白名单,会同时把新名称加入,使平台校验自动放行;
  3. 引擎侧 get_quantization_config() 在查表时,先用内置的 method_to_config 映射解析(覆盖 awqfp8gptq_marlincompressed-tensorsmodelopttorchaoquarkonline 等),随后执行 method_to_config.update(_CUSTOMIZED_METHOD_TO_QUANT_CONFIG) 合并自定义注册项——因此自定义方法天然被同一条解析路径覆盖。

值得注意的两点实现细节:

  • 若注册的名称与内置方法重名,只会输出 debug 日志并直接覆盖,不会报错;
  • QuantizationMethods 是一个 Literal 类型(init.py 第 15-49 行),其中既包含检查点方法(如 fp8awq_marlin),也包含在线量化的简写名(如 fp8_per_tensorint8_per_channel_weight_onlynvfp4_per_token),二者共用同一个 --quantization 参数入口。

注册自定义量化方法

注册步骤:创建一个继承自 QuantizationConfig 的类,并用 @register_quantization_config 装饰。get_quant_method 按层类型把调度分发到具体的量化方法。完整示例(继承自官方文档):

import torch
from vllm.model_executor.layers.quantization import (
    register_quantization_config,
)
from vllm.model_executor.layers.quantization.base_config import (
    QuantizationConfig,
    QuantizeMethodBase,
)
from vllm.model_executor.layers.linear import LinearBase
from vllm.model_executor.layers.fused_moe import FusedMoE

@register_quantization_config("my_quant")
class MyQuantConfig(QuantizationConfig):
    """Custom quantization config."""

    def get_name(self) -> str:
        return "my_quant"

    def get_supported_act_dtypes(self) -> list:
        return [torch.float16, torch.bfloat16]

    @classmethod
    def get_min_capability(cls) -> int:
        # Minimum GPU compute capability, -1 for no restriction
        return -1

    @staticmethod
    def get_config_filenames() -> list[str]:
        # Config files to search for in model directory
        return []

    @classmethod
    def from_config(cls, config: dict) -> "MyQuantConfig":
        # Create config from model's quantization config
        return cls()

    def get_quant_method(
        self, layer: torch.nn.Module, prefix: str
    ) -> QuantizeMethodBase | None:
        # Dispatch based on layer type
        # NOTE: you only need to implement methods you care about
        if isinstance(layer, LinearBase):
            return MyQuantLinearMethod()
        elif isinstance(layer, FusedMoE):
            return MyQuantMoEMethod(layer.moe_config)
        return None

必须实现的 QuantizationConfig 抽象方法

QuantizationConfig 基类定义在 vllm/model_executor/layers/quantization/base_config.py,自定义子类必须实现以下抽象方法:

方法 说明
get_name() 返回量化方法名称
get_supported_act_dtypes() 返回支持的激活 dtype 列表(如 torch.float16
get_min_capability() 返回最低 GPU 算力等级(如 Ampere 为 80,无限制则返回 -1)
get_config_filenames() 返回在模型目录中需要搜索的配置文件名列表
from_config(config) 类方法,从模型量化配置字典创建配置对象
get_quant_method(layer, prefix) 给定层返回对应量化方法;返回 None 表示跳过该层

其中 get_quant_method(layer, prefix) 的第二个参数 prefix 是该层在 state dict 中的完整名称,可实现按层名前缀做选择性量化(例如只对 mlp 相关前缀启用)。基类还提供了两个便捷工具:get_from_keys / get_from_keys_or,用于从量化配置字典中按候选键名取值,键名缺失时抛错或回退默认值。

实现量化 Linear 方法

对于线性层,get_quant_method 返回 QuantizeMethodBase 的子类。可以以 UnquantizedLinearMethodlinear.py 中定义)为起点继承扩展:

from vllm.model_executor.layers.linear import UnquantizedLinearMethod

class MyQuantLinearMethod(UnquantizedLinearMethod):
    """Custom quantization method for linear layers."""

    def create_weights(
        self, layer: torch.nn.Module, *weight_args, **extra_weight_attrs
    ):
        # Create quantized weights for the layer
        ...

    def apply(
        self,
        layer: torch.nn.Module,
        x: torch.Tensor,
        bias: torch.Tensor | None = None,
    ) -> torch.Tensor:
        # Apply custom quantization logic here
        ...

从源码结构看,QuantizeMethodBasebase_config.py 第 23-82 行)的完整生命周期接口不止 create_weightsapply 两个抽象方法,还包括若干可选钩子:

  • process_weights_after_loading(layer):权重加载完成后的后处理点,典型用途是转置、重打包权重以匹配内核布局;
  • embedding(layer, *args):仅当子类真正覆写了该函数时(由 method_has_implemented_embedding 检查是否与基类实现不同)才会被调用,用于量化嵌入查表;
  • tie_weights(layer, embed_tokens):处理词嵌入与 LM Head 的权重共享(tied weights),需要特殊权重布局的量化方法需覆写;
  • 类属性 uses_meta_device:标记该方法在在线量化时是否在 meta 设备上建权重、逐层量化以降低加载峰值显存;
  • 类属性 supports_pre_processed_weights:声明 process_weights_after_loading 是否支持幂等重入。

实现量化 MoE 方法

对于混合专家(MoE)模型,get_quant_method 应返回 FusedMoEMethodBasefused_moe_method_base.py 第 28 行起)的子类;若不需要量化 MoE,可退回到 UnquantizedFusedMoEMethodunquantized_fused_moe_method.py 第 45 行):

from vllm.model_executor.layers.fused_moe.layer import UnquantizedFusedMoEMethod
from vllm.model_executor.layers.fused_moe.fused_moe_method_base import (
    FusedMoEMethodBase,
)
from vllm.model_executor.layers.fused_moe.config import FusedMoEQuantConfig

class MyQuantMoEMethod(FusedMoEMethodBase):
    """Custom quantization method for MoE layers."""

    def create_weights(
        self,
        layer: torch.nn.Module,
        num_experts: int,
        hidden_size: int,
        intermediate_size_per_partition: int,
        params_dtype: torch.dtype,
        **extra_weight_attrs,
    ):
        # Create quantized weights for the MoE layer
        ...

    def apply(
        self,
        layer: torch.nn.Module,
        router: "FusedMoERouter",
        x: torch.Tensor,
        router_logits: torch.Tensor,
    ) -> torch.Tensor:
        # Apply MoE computation with quantized weights
        ...

    def get_fused_moe_quant_config(
        self, layer: torch.nn.Module
    ) -> FusedMoEQuantConfig | None:
        # Return the MoE quantization configuration
        ...

其中 FusedMoEQuantConfig 定义在 fused_moe/config.py 第 214 行。编写参考实现时,官方文档建议直接阅读 Fp8MoEMethod——它位于 vllm/model_executor/layers/quantization/fp8.py 第 481 行,展示了 MoE 层创建量化权重、绑定 MoE 内核配置的标准写法;同文件第 216 行附近可见 Fp8Config.get_quant_methodFp8MoEMethod(self, layer) 的调度方式。

使用插件

注册完成后即可像内置方法一样通过 quantization 参数启用自定义量化:

# Register your quantization method (import the module containing your config)
import my_quant_plugin

from vllm import LLM

# Use the custom quantization method
llm = LLM(model="your-model", quantization="my_quant")

关键点:自定义插件模块必须在构造 LLM 之前被 import,确保装饰器完成注册;插件体系的整体设计(含加载时机与扩展点)可参阅 Plugin System 设计文档

量化方法的最终解析路径:resolve_quant_method

从源码结构看,模型初始化时每个被量化的层会经由 resolve_quant_method() 得到最终的量化方法。该函数的行为体现了“检查点量化优先、在线量化兜底”的原则:

  1. 先调用 quant_config.get_quant_method(layer, prefix) 取得检查点声明的方法;
  2. 若未配置在线量化(online_quantization_config is None),直接返回检查点方法;
  3. 在线量化目前仅接管 LinearBaseRoutedExperts 两类层,Embedding 与 LM Head 保留检查点方法;
  4. 若层已在检查点中被量化,再请求在线量化会直接抛出 ValueError,防止对已量化权重重复量化。

这条路径解释了为什么自定义插件只需覆写 get_quant_method 的层类型分发:无论是否叠加在线量化,自定义方法都在这一步被统一解析。

小结与延伸阅读

登录后查看全文
热门项目推荐
相关项目推荐