模型级精度映射
模型级精度映射回答的是模型的哪些部分使用什么精度,量化算法回答的是低精度参数如何生成。主流推理引擎并不会任意给每一层分配 bit,而是把少数计算密集型模块替换为硬件支持的低精度实现,其余算子保留模型 dtype,再独立配置 KV Cache。
一、精度策略不等于量化算法
对线性层 W4A16、W8A8 只描述 weight 和 activation,完整实现还要决定累加、输出以及相邻算子的精度:
其中,
| 层次 | 需要决定的问题 | 例子 |
|---|---|---|
| 精度策略 | 哪些模块或状态使用哪种 dtype | Linear 使用 W4A16,Norm 使用 BF16,KV Cache 使用 FP8 |
| 量化算法 | 如何得到低精度 weight、activation 和 scale | GPTQ、AWQ、SmoothQuant、RTN |
| 执行后端 | 哪个 kernel 消费这种格式 | Marlin、CUTLASS、DeepGEMM、oneDNN |
同一种精度策略可以由不同算法生成。例如,GPTQ、AWQ 和 AutoRound 都可以生成 W4A16 checkpoint;对推理引擎而言,真正决定执行路径的是 checkpoint 格式、模块范围和可用 kernel,而不是算法名称。
二、主流实现:替换 Linear/MoE,外围保持高精度
这是服务器推理中最常见的实现。推理框架只为 Linear 和 FusedMoE 等矩阵乘模块安装低精度 method;RMSNorm、Softmax、RoPE、Residual Add 和激活函数没有被量化配置替换,继续使用模型 dtype 或算子内部指定的更高精度。
BF16/FP16 hidden states
→ Quantized Linear / Fused MoE
Weight: W4 / W8 / FP8 / FP4
Activation: A16 / A8 / A4
Accumulate: kernel-defined wider dtype
Output: BF16 / FP16
→ Norm / RoPE / Softmax / Residual in model dtypeSGLang 的 W8A8 FP8 配置就是这种分派:LinearBase 使用 FP8 Linear method,FusedMoE 使用 FP8 MoE method,其他模块返回 None。通用 FP8 配置还会让 ignored_layers 返回未量化的 Linear/MoE method。
📄 SGLang `w8a8_fp8.py`
def get_quant_method(self, layer, prefix):
if isinstance(layer, LinearBase):
return W8A8Fp8LinearMethod(self)
elif isinstance(layer, FusedMoE):
return W8A8FP8MoEMethod(self)
return None这类实现形成两种最常见的主体配置:
| 主体配置 | Linear/MoE | 外围算子 | 主要使用场景 |
|---|---|---|---|
| W4A16 | 4-bit weight,BF16/FP16 activation | BF16/FP16,部分归约内部使用 FP32 | 权重容量或 decode 带宽受限 |
| W8A8 / FP8 | INT8/FP8 weight 与 activation | BF16/FP16,部分归约内部使用 FP32 | 有原生低精度 GEMM 的服务器硬件 |
算法只负责把主体模块准备成对应格式。例如 AWQ/GPTQ 常用于生成 W4A16,SmoothQuant 或动态量化可用于准备 W8A8;它们不是这张模块级精度图本身。完整组合见量化配置。
三、少量高精度 fallback
主流框架普遍支持 ignore、ignored_layers 或 modules_to_not_convert,用于让少数模块回退到 BF16/FP16。它解决的是具体模型或 kernel 的兼容性问题,不代表存在一份所有模型通用的“敏感层名单”。
业界实现中常见的 fallback 包括:
- LM Head:vLLM 的在线 FP8 路径和 LLM Compressor 示例默认跳过最终
lm_head,但支持的后端也可以选择量化它。 - 多模态 Encoder/Projector:参数占比小且直接影响语言模型输入质量时,常保留 BF16/FP16 或 Q8。
- 不受支持的 Projection/Gate:融合布局或 MoE kernel 无法消费其格式时,保持原始精度。
- 校准发现的敏感模块:通过逐模块消融确认后加入 skip list,而不是预设首层、尾层一定敏感。
vLLM 的在线量化配置把模块例外直接暴露为精度路由:
quantization_config:
linear: fp8_per_block
moe: fp8_per_tensor
ignore:
- lm_head
- "re:.*[qkv]_proj"融合算子会限制 fallback 的粒度。例如 QKV 已打包为一个 fused tensor 时,不能假设 q_proj、k_proj、v_proj 可以任意使用三种位宽;配置必须符合框架的 shard 匹配和 kernel 布局。
四、按模型组件划分精度
在 MoE 和低至 FP4 的部署中,按组件划分比任意逐层 mixed-bit 更常见。原因是组件边界通常对应独立 kernel,容易保留规则的数据布局。
1. Dense Linear 与 MoE 分开配置
vLLM 在线量化为 linear 和 moe 提供独立配置。部署者可以让 Dense Linear 使用 per-block FP8,而 Fused MoE 使用 per-tensor FP8,或者反向组合;未配置的一侧继承默认方案。
2. 只量化 MLP 或 Routed Expert
NVIDIA ModelOpt 提供以下实际导出配方:
nvfp4_mlp_only:只量化 MLP 和 MoE,Attention 保持较高精度。nvfp4_experts_only:只量化 MoE Routed Expert。nvfp4_omlp_only:在 MLP-only 基础上增加 Attentiono_proj。
这类配方利用了 MLP/Expert 参数占比高、组件边界清楚的特点。它不意味着 Router、Shared Expert 或 Attention 必须使用某个固定 dtype;具体精度仍由 checkpoint 配方定义。
3. 本地推理的跨 tensor 混合
llama.cpp 的 GGUF 生态广泛使用跨 tensor 混合预设。以 Q4_K_M 为例,主体使用 Q4_K,部分 tensor 按内置规则提高位宽;--pure 用于关闭这种 mixture。量化器还支持单独设置 output.weight、token embedding 或正则匹配的 tensor 类型。
这种 tensor 级混合适合 llama.cpp 已实现相应块格式和算子的场景,不应直接外推到所有 GPU serving 框架。GGUF 的具体规则见llama.cpp:K-Quant 与 I-Quant。
五、算子内部使用更宽的累加精度
低精度输入不等于全程低精度。INT8 GEMM 通常使用 INT32 partial sum,再应用 scale 并输出 BF16/FP16;FP8/FP4 kernel 也会按硬件指令选择更宽的 accumulator 和输出 dtype。
Normalization 和 Softmax 的归约也可能在 FP32 内部完成,再转回输入 dtype。例如本站 Qwen2 实现中的 RMSNorm 方差统计与 eager Softmax 都显式使用 FP32。
这部分精度通常由 kernel 或算子实现决定,而不是 checkpoint 中的 WnAm 名称决定。评估一条低精度路径时需要同时确认 input、accumulator 和 output dtype。
六、KV Cache 独立于模型精度
TensorRT-LLM、vLLM 和 SGLang 都把 KV Cache dtype 作为独立配置。以下组合都可以成立:
W4A16 model + BF16/FP16 KV Cache
W4A16 model + FP8 KV Cache
FP8 W8A8 model + FP8 KV Cache
BF16 model + FP8 KV CacheKV Cache 随 batch 和上下文长度增长,优化目标与静态 weight 不同。短上下文下可以保持 BF16/FP16;长上下文或高并发下再评估 FP8,部分新后端还支持 FP4。还要确认 Attention kernel 是否融合了反量化,否则 Cache 变小不一定带来吞吐提升。
存储精度也不必等于 Attention 计算精度:有的 backend 读取低精度 Cache 后转为 BF16/FP16,有的 backend 可以直接在 FP8 域完成部分计算。
八、业界实现对照
| 实现 | 主要精度控制入口 | 已落地的混合方式 |
|---|---|---|
| vLLM | quantization、quantization_config.linear/moe/ignore、kv_cache_dtype | Linear/MoE 分区、模块 fallback、独立 KV Cache |
| SGLang | QuantizationConfig method dispatch、ignored_layers、--kv-cache-dtype | Linear/FusedMoE 替换、未量化 fallback、独立 KV Cache |
| TensorRT-LLM | W4A16/W4A8/FP8/FP4 recipe、KvCacheConfig | 固定硬件 recipe、模型与 KV Cache 分离 |
| ModelOpt | nvfp4_mlp_only、nvfp4_experts_only 等导出配方 | MLP/Expert/Attention 组件级划分 |
| llama.cpp | K-Quant/I-Quant preset、--tensor-type、--pure | GGUF 跨 tensor 混合 bit |
这里最普遍的是“主体 Linear/MoE 低精度 + 外围算子保持模型 dtype + 少量 fallback + KV Cache 独立配置”。组件级 FP4 和 GGUF tensor mixture 是针对特定硬件或运行时的扩展;任意 per-layer mixed-bit 并不是所有后端都能直接执行的通用能力。
参考
- vLLM: Online Quantization
- vLLM: Quantization Support Matrix
- vLLM: Quantized KV Cache
- SGLang: Quantization
- SGLang: Quantized KV Cache
- SGLang: W8A8 FP8 Method Dispatch
- NVIDIA TensorRT-LLM: Quantization
- NVIDIA Model Optimizer: LLM PTQ
- NVIDIA Model Optimizer:
auto_quantize - llama.cpp:
llama-quantize - LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale