💡 一句话总结:长上下文推理真正的内存墙不是权重,而是随上下文线性膨胀的 KV Cache。vLLM 里一行参数就能开 FP8 量化拿到约 2 倍容量、接近无损;但要记住它换的是显存不是吞吐,且任何更激进的方案都必须用 NIAH 验证长上下文不掉点。
一、被忽视的内存墙
聊量化,大多数人第一反应是 AWQ、GPTQ——把模型权重压到 4-bit。但在真实的长上下文服务里,权重往往不是最吃显存的那块。
原因在 KV Cache:自回归解码时,每生成一个 token,注意力机制就要把这一步的 Key、Value 缓存下来,供后续步骤复用。这个缓存的大小,正比于「层数 × 注意力头数 × 头维度 × 上下文长度 × batch」。权重是固定的一次性开销,KV Cache 却随上下文长度线性增长。
举个直观的数:一个中等规模模型,跑到 128K 上下文、几十路并发,KV Cache 能轻松吃掉几十 GB——经常比权重本身还大。这就是为什么长上下文服务一上量就 OOM,而你盯着权重量化怎么调都不解决问题。短上下文看权重,长上下文看 KV Cache。
好消息是:KV Cache 和权重压的是两个不同的内存池,互补而非互斥。你可以先 AWQ 压权重,再在其上叠 FP8 压 KV Cache,收益相加。
二、量化谱系:从 FP8 到 4-bit 以下
KV Cache 量化这几年方案不少,按压缩力度大致排成一条谱系:
- FP8(E4M3):当下默认。约 2 倍容量,吞吐接近 BF16,质量损失通常 <1%。门槛低、生态成熟,是任何新方案要超越的基准线。
- INT 4-bit(KIVI、GEAR):把键值压到 4-bit 整数,理论容量翻倍以上。问题在开销——把高维浮点向量塞进低位整数,反量化和分组缩放的成本不低,且对分布敏感。
- TurboQuant(Google):今年抢了不少头条的激进方案,压缩可达 5-6 倍。代价是长上下文检索容易失效——公开实现里甚至把首尾若干层留作 FP16 不量化,以保住关键层的精度。
- KVarN(华为):方差归一化的 KV Cache 量化(Variance-Normalized)。核心是缓解低位量化的误差累积,论文显示在推理(reasoning)任务上比 TurboQuant 这类更稳——激进压缩往往在需要多步推理时崩得最明显,KVarN 正是冲着这个痛点去的。
- 向量量化路线(Apple 等):用 codebook 做加性量化,配合 RoPE 可交换的设计降低解码开销,追求更高压缩比下的精度。
记住一个判断原则:压缩比越高,越要警惕长上下文检索和多步推理这两个失效区。困惑度这种平均指标看不出问题,针对性测试才能。
三、实战:在 vLLM 里开 FP8 KV Cache
vLLM 原生支持 FP8 KV Cache,开启只要一个参数。最简单的离线推理:
from vllm import LLM, SamplingParams
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
kv_cache_dtype="fp8", # 开启 FP8 KV Cache(默认 E4M3)
max_model_len=131072, # 长上下文才是 KV 量化的主场
)
out = llm.generate(
["把这份长文档总结成 5 条要点:..."],
SamplingParams(temperature=0.2, max_tokens=512),
)
print(out[0].outputs[0].text)
起服务则是:
vllm serve meta-llama/Llama-3.1-8B-Instruct \
--kv-cache-dtype fp8 \
--max-model-len 131072
注意一个限制:vLLM 目前只支持 FP8(E4M3/E5M2)KV Cache,不支持 INT8 KV Cache。如果你看到某些框架对比里 INT8 KV 的数据,那是 TensorRT-LLM 等其他引擎的能力,别照搬到 vLLM 配置上。
四、scale 怎么定:三种校准方式
FP8 量化要把浮点值映射到 8-bit,需要一个缩放因子 scale。vLLM 给了三档,从省事到精确:
- 未校准(scale = 1.0):什么都不做,per-tensor 固定 scale。这是最坏情况下限,胜在零成本、可复现。vLLM 官方的评测就常用这档来给「下限」托底。
- 随机 token 在线校准:warmup 阶段用一批随机 token 自动估出 scale 然后固定。配置
calculate_kv_scales=True:
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
kv_cache_dtype="fp8",
calculate_kv_scales=True, # 用随机 token 在线估 scale
)
- 校准数据集离线生成 scale:用一批贴近真实分布的语料离线跑出每层/每头的 scale,写进权重附带的量化配置。最准,但要多一步离线流程。
经验法则:先用 scale=1.0 测出下限,再用随机 token 校准看能不能拉回来;只有当业务对精度极敏感、且简单校准不够时,才上数据集离线校准。 别一上来就堆最重的方案。
五、验证:NIAH 才是试金石
量化后最危险的不是平均质量掉一点,而是长上下文深处的信息悄悄丢了。困惑度、几道常规 benchmark 都可能看不出来。
正确的验证是 Needle-In-A-Haystack(NIAH):
- 准备一段很长的背景文本(覆盖你的目标上下文长度,比如 8K、32K、128K)。
- 在文本里插入一条具体、随机、与背景无关的「针」,例如「2026 年巴黎的隐藏密码是 7391」。
- 把针放到不同深度(开头、10%、50%、90%、结尾),分别让模型回答「密码是多少」。
- 对每个(上下文长度 × 深度)组合记录是否命中,画成热力图。
伪代码:
def niah_probe(llm, depth_ratio, ctx_len):
needle = "2026 年巴黎的隐藏密码是 7391。"
bg = make_background(ctx_len) # 拼到目标长度
pos = int(len(bg) * depth_ratio)
prompt = bg[:pos] + needle + bg[pos:] + "\n请问隐藏密码是多少?"
ans = llm.generate([prompt]).outputs[0].text
return "7391" in ans # 命中判定
# 跑满矩阵:FP8 与 BF16 各跑一遍,对比热力图
把 FP8 的热力图和 BF16 基线叠一起看。FP8 通常整张图全绿、和基线几乎一致;一旦你换上 4-bit 以下的激进方案,深处的格子开始变红——这正是 TurboQuant 这类方案需要保留首尾层 FP16 的原因。
六、一个反直觉的事实:你换的是显存,不是吞吐
很多人开 FP8 KV Cache 是冲着「更快」去的,结果跑完 benchmark 一脸困惑:吞吐没涨,prefill-heavy 场景甚至略降。
这不是 bug。在 vLLM 上,FP8 KV Cache 的主要收益是省显存,不是直接加速:解码时算的仍是反量化后的注意力,量化/反量化本身还要花时间。它真正的价值是间接的——省下的显存让你能开更大的 batch、更长的上下文、更高的并发,整体吞吐和服务容量随之上去。
如果你要的是「KV 量化直接换吞吐」,那是 TensorRT-LLM 的强项——它的 FP8/INT8 KV Cache 在吞吐上有更明显的正收益。所以选型前先问自己一句:我现在缺的是显存,还是算力? 答案不同,结论完全不同。
七、KVarN:当 FP8 不够省时
如果 FP8 的 2 倍还填不满你的长上下文需求,下一步往往是 4-bit 以下,而这正是华为 KVarN 想解决的场景。它的思路是方差归一化:低位量化误差会随 token 累积,KVarN 在量化前对键值按方差做归一化,让分布更适合低位表示,从而压住误差累积——尤其是在多步推理任务里,激进压缩最容易崩的地方。
概念性伪代码(表达思路,非可运行实现):
def kvarn_quantize(kv, bits=4):
# 1. 按通道估方差,做归一化,让分布更"齐整"
var = kv.var(dim=-1, keepdim=True)
kv_norm = kv / (var.sqrt() + 1e-6)
# 2. 在归一化后的空间做低位量化
q, scale = low_bit_quant(kv_norm, bits=bits)
# 3. 反量化时把方差缩放还原回去
return q, scale, var
要不要上?给个决策清单:
- 显存够、要稳:FP8(E4M3)+ 随机 token 校准,收工。
- 显存紧、上下文长、能离线:在 FP8 之外灰度试 4-bit 方案(KVarN / TurboQuant),务必跑 NIAH + 你的真实推理任务双重验证。
- 要吞吐不要显存:别在 vLLM 死磕 KV 量化,考虑 TensorRT-LLM,或先优化 batch 调度与 prefix caching。
- 追前沿:KVarN 这类方案先在内部基准上复现,确认框架/算子支持就绪,再谈生产。
八、小结
KV Cache 才是长上下文推理的内存墙。vLLM 上一行 kv_cache_dtype=fp8 就能拿到约 2 倍容量、接近无损的确定收益,记住它换的是显存而非吞吐。任何更激进的方案——TurboQuant、KVarN——都别只看压缩比,先用 NIAH 和你的真实推理任务把长上下文这关守住。先拿稳的,再追狠的。