CANN-ATB量化推理-昇腾NPU上W8A8量化为什么比W4A16更实用
Llama2-70B 权重 140GB8 卡 TP 刚好放得下但没什么余量给 KV Cache。W8A8 量化把权重从 fp16 压到 int8权重体积减半4 卡就能跑 70B。W4A16 理论上压得更狠4 倍压缩但精度损失在实际业务里往往不可接受。ATB 的量化推理模块支持两种方案这篇帮你选。量化方案对比方案权重精度激活精度压缩比精度损失W16A16fp16fp161×无baselineW8A8int8int82×0.1-0.5%W4A16int4fp164×1-5%W8A16int8fp162×0.05-0.2%W4A16 压缩比最高但精度损失大。W8A8 精度好但需要激活也做 int8 量化实现复杂度更高。W8A16 是最保守的选择——权重 int8 但激活保持 fp16。ATB 的 W8A8 实现fromatbimportLLM modelLLM(meta-llama/Llama-2-70b-hf,devicenpu:0,1,2,3,tensor_parallel_size4,quantizew8a8# W8A8 量化)ATB 的 W8A8 量化流程1. 权重离线量化fp16 权重 → int8 权重 scale 2. 运行时反量化int8 权重 × scale → fp16 → MatMul 3. 激活量化fp16 激活 → int8 激活 scale 4. int8 MatMulint8 权重 × int8 激活 → int32 结果 5. 反量化int32 结果 × weight_scale × act_scale → fp16步骤 2 的反量化走 DMA 引擎零计算开销。步骤 4 的 int8 MatMul 在昇腾NPU的 Cube 单元上有原生支持——int8 GEMM 的算力是 fp16 GEMM 的 2 倍因为 Cube 单元的 int8 吞吐量是 fp16 的 2 倍。ATB 的 W4A16 实现modelLLM(meta-llama/Llama-2-70b-hf,devicenpu:0,1,tensor_parallel_size2,quantizew4a16# W4A16 量化)W4A16 的权重是 4bit但 MatMul 不支持 4bit 输入。所以需要先反量化到 fp16 再算1. 权重离线量化fp16 → int4 scale zero_point 2. 运行时反量化int4 → fp16每个权重需要查表缩放 3. fp16 MatMul反量化后的 fp16 权重 × fp16 激活步骤 2 是瓶颈。4bit 反量化需要逐组group_size128做查表和缩放走 Vector 单元。反量化时间约占 MatMul 总时间的 20-30%。4bit 省了权重存储和 HBM 读取但反量化的额外计算把一部分收益吃回去了。实测精度Llama2-70B 在 MMLU 和 GSM8K 上的精度对比方案MMLU (5-shot)GSM8K (8-shot)W16A16 (baseline)69.8%57.4%W8A1669.5%57.0%W8A869.0%56.2%W4A16 (GPTQ)67.2%51.8%W4A16 在 GSM8K 上掉了 5.6 个点——数学推理对精度特别敏感。W8A8 只掉了 1.2 个点大部分业务可以接受。性能数据Atlas 800I A2 × 4Llama2-70B方案decode 速度 (tokens/s)单卡显存 (GB)最大并发W16A16 (TP8)2,4003516W8A8 (TP4)2,8004212W8A16 (TP4)2,6004212W4A16 (TP2)1,800388W8A8 的 decode 速度反而比 W16A16 快——int8 GEMM 的算力翻倍在 compute-bound 的 prefill 阶段收益最大。W4A16 看似省显存但速度最慢因为反量化开销。建议显存够用不量化fp16 跑显存紧但精度不能降W8A16最安全的量化想省卡 接受微小精度损失W8A82 倍压缩 2 倍 GEMM 算力极端省显存场景W4A16但要对精度做充分评估量化不是免费的午餐。W8A8 是当前昇腾NPU上性价比最高的方案——精度损失小、int8 GEMM 有硬件加速。W4A16 除非你真的放不下模型否则不建议。仓库在这里https://atomgit.com/cann/ATB