量化 KV 缓存#

量化 KV 缓存通过使用低精度数据类型(FP8 或 FP4)代替默认的 BF16 模型精度,来减少键值(KV)缓存存储的内存占用。在自回归生成过程中,大语言模型(LLM)会缓存先前计算的键值对,以避免冗余计算。KV 缓存通常消耗很大一部分 GPU 内存,尤其是在处理长序列时。

量化 KV 缓存是一种内存优化技术,它通过允许缓存更多标记(tokens)来主要提升吞吐量,但根据所使用的量化格式,可能会引入极小的精度损失。

警告

性能警告:当必须在注意力(attention)操作前对量化 KV 缓存进行反量化时,如果反量化过程没有与注意力算子融合(fused),性能可能会变得非常缓慢。请务必核实您选择的注意力后端是否支持量化 KV 缓存。不支持融合算子的后端可能会出现严重的吞吐量下降,甚至抵消掉内存带来的收益。

后端支持:并非所有注意力后端都支持量化 KV 缓存。请参考 注意力后端 了解哪些后端支持此功能。

支持的格式#

SGLang 支持以下量化 KV 缓存格式

FP8 格式#

OCP (Open Compute Project) 规定了两种通用的 8 位浮点格式

  • E5M2 (5 位指数,2 位尾数):动态范围更大 (±57344.0),精度较低

  • E4M3 (4 位指数,3 位尾数):精度更高,动态范围较小 (±240.0)

FP4 格式#

警告

FP4 量化目前处于实验阶段。

OCP (Open Compute Project) 规定了 MXFP4 (Microscaling FP4),这是一种 4 位浮点格式

  • E2M1 (1 位符号位,2 位指数,1 位尾数):使用基于块的微缩放(microscaling),其中张量被划分为连续元素的块,每个块共享一个 8 位指数缩放因子。虽然 OCP 规定块大小为 32 个元素,但 SGLang 当前在 KV 缓存量化中的实现使用 16 个元素的块。

用法#

启用量化 KV 缓存#

要启用量化 KV 缓存,请在启动服务器时使用 --kv-cache-dtype 参数

# Enable FP8 E5M2 KV cache
python3 -m sglang.launch_server \
    --model-path deepseek-ai/DeepSeek-R1-0528 \
    --kv-cache-dtype fp8_e5m2 \

# Enable FP8 E4M3 KV cache
python3 -m sglang.launch_server \
    --model-path deepseek-ai/DeepSeek-R1-0528 \
    --kv-cache-dtype fp8_e4m3 \

# Enable FP4 E2M1 KV cache
python3 -m sglang.launch_server \
    --model-path nvidia/DeepSeek-R1-0528-NVFP4 \
    --kv-cache-dtype fp4_e2m1 \

缩放因子#

FP8 量化需要缩放因子来正确地对 KV 缓存进行量化和反量化。

注意

目前仅支持每张量(per-tensor/标量)缩放因子。

缩放因子可以通过以下方式获取:

  • 从检查点(checkpoints)加载:预量化模型(例如 ModelOpt)可能包含会自动加载的 k_scalev_scale 参数

  • 通过 JSON 提供:通过 --quantization-param-path 提供缩放因子。

JSON 文件应遵循以下格式

{
  "kv_cache": {
    "dtype": "float8_e4m3fn",
    "scaling_factor": {
      "0": {
        "0": 1.0,
        "1": 1.0
      }
    }
  }
}

其中 scaling_factor 的外层键是张量并行(TP)秩,内层键是层索引。

警告

如果未提供缩放因子且在检查点中未找到,将默认使用 1.0,这可能会导致精度问题。

提示

FP4 (MXFP4):与 FP8 不同,FP4 量化在量化和反量化过程中自动实时处理缩放因子。不需要预量化模型或外部缩放因子文件——基于块的缩放因子是根据需要动态计算的。

性能考量#

内存节省#

量化 KV 缓存提供了显著的内存节省

  • BF16 → FP4:支持比 BF16 多约 3.56 倍的标记(考虑到缩放因子的开销)

注意

FP4 和 FP8 量化需要额外的内存来存储基于块的缩放因子,这与单纯的位宽减少相比,降低了实际的内存节省。块大小为 16 的 FP4 支持的标记数量约为 FP8 的 1.78 倍,约为 BF16 的 3.56 倍。FP8 与 BF16 之间的相对标记容量可以从这些比例中推导出来。

这使得在相同的内存预算下,可以实现更长的上下文长度或更多的并发请求。

精度影响#

FP8 精度#

FP8 E4M3 量化通常引入极小的精度损失。其影响取决于模型架构、序列长度和量化格式(通常 E4M3 的精度优于 E5M2)。

FP4 精度#

FP4 (MXFP4) 量化在显著节省内存的同时,其精度影响因模型大小和数据集复杂度而异。来自 PR #10078 (MLA) 和 PR #12612 (MHA) 的初步精度测试结果显示:

大型模型(例如 Qwen3-235B-A22B, DeepSeek-R1-0528)

在大型模型上,FP4 保持了接近 FP8/BF16 的精度,尤其是在简单的数据集上

模型

数据集

KV16

KV8 (FP8 E4M3)

KV4 (FP4 E2M1)

Qwen3-235B-A22B

gsm8k

0.9168

0.9181

0.9186

Qwen3-235B-A22B

aime25

0.7733

0.7333

0.6000

Qwen3-235B-A22B

gpqa_diamond

0.7010

0.6899

0.6778

DeepSeek-R1-0528

gsm8k

0.9157

0.9154

0.9124

DeepSeek-R1-0528

aime25

0.5067

0.4934

0.4000

DeepSeek-R1-0528

gpqa_diamond

0.7707

0.7697

0.7273

较小型模型(例如 GPT-OSS-120B)

在较小型模型上,FP4 显示出更明显的精度下降,特别是在具有挑战性的数据集上

模型

数据集

KV16

KV8 (FP8 E4M3)

KV4 (FP4 E2M1)

GPT-OSS-120B

gsm8k

0.9161

0.9163

0.9152

GPT-OSS-120B

aime25

0.7533

0.7667

0.3533

GPT-OSS-120B

gpqa_diamond

0.5081

0.5434

0.3202

关键结论

  • 简单数据集(如 gsm8k):在不同规模的模型中,FP4 均能保持接近 FP8/BF16 的精度

  • 模型大小至关重要:大型模型(200B+ 参数)通常比小型模型更能容忍 FP4 量化

  • 上下文长度:在长上下文场景中,精度下降可能更为明显,因为量化误差的累积可能会变得显著。

提示

请针对您的特定模型和工作负载评估 FP4 的精度。处理简单任务的大型模型通常显示出极小的下降,而小型模型或复杂的推理任务可能需要 FP8 或 BF16 才能获得可接受的精度。

最佳实践#

  • 使用预量化模型:优先选择离线量化且检查点中包含缩放因子的模型。

  • 选择正确的格式:使用 fp8_e4m3 以获得更好的精度(推荐),使用 fp8_e5m2 以获得更大的动态范围,或使用 fp4_e2m1 以实现最大的内存节省(实验性)

  • 检查后端兼容性:核实您选择的注意力后端是否支持量化 KV 缓存