混合精度推理如何选择不同层的精度?
简化版
混合精度不是凭经验把首尾层留成 FP16,而是在质量约束下,把高精度预算分给量化敏感的层、通道和算子。先建立统一低比特基线,再逐层/逐块恢复高精度,测任务损失、激活 Outlier、Hessian/梯度敏感度与真实硬件收益。
常见高敏感位置包括 Embedding、LM Head、少数 Attention/MLP 层和 Outlier 通道,但不同模型与任务结论不同。最终配置还要避免频繁精度转换和低效 Kernel,按质量、显存、TTFT/TPOT、吞吐和功耗选 Pareto 点。
详细版
baseline low-bit -> sensitivity scan -> allocate precision budget
-> calibrate/export -> target-runtime benchmark
-> task/safety regression
| 信号 | 含义 | 局限 |
|---|---|---|
| 逐层量化 Loss 增量 | 直接反映局部敏感度 | 成本高、交互未建模 |
| 激活范围/Outlier | 量化难度 | 不等于任务重要性 |
| Hessian/梯度 | 参数扰动敏感 | 近似和数据依赖 |
| 下游任务退化 | 最接近目标 | 样本量与成本高 |
精度分配可设成预算优化:在显存/延迟上限内最小化验证损失;候选档位离散为 FP16、INT8、INT4 等,减少搜索与运行时碎片。
完整版教学
1. 为什么不同层敏感度不同
各层权重分布、激活范围、残差位置和功能不同。相同量化误差在关键层可能被后续放大,在冗余层则被残差吸收。
因此全模型统一位宽简单但未必是最佳质量—成本点。
2. 混合精度的优化目标
minimize validation_loss(bit_assignment)
subject to memory <= budget
latency <= SLO
它是离散组合优化,工程上用敏感度排序、贪心、搜索或学习式方法近似。
3. 如何建立统一基线
先测 FP16 与全 INT8/INT4 的质量、内存和性能,确认主要退化与目标收益。没有两端基线,无法判断混合方案是否值得复杂度。
校准、数据、Kernel 和解码配置保持一致,避免把其他变量误归因给位宽。
4. 逐层消融怎么做
以低比特模型为起点,每次把一个层/模块恢复高精度,测验证指标增益;或从高精度出发逐层量化,测损失增量。
两种方向可能因层间交互得到不同排序,应对最终组合再做整体验证。
为降低成本,可先用小校准集筛出前 20% 敏感候选,再在完整任务集上复测;每次消融记录同一 Seed 和缓存状态,避免生成随机性干扰微小差异。
5. 哪些模块常被保留
Embedding 与 LM Head 直接连接离散 Token,少数 Outlier 明显层、首尾层或 Attention 投影可能敏感,但这只是候选。
| 模块 | 保留高精度的可能原因 |
|---|---|
| Embedding | 稀有 Token 表示脆弱 |
| LM Head | 小 Logit 差决定输出 |
| Attention | 排序误差影响检索位置 |
| MLP | Outlier 与知识通道 |
| Norm | 数值范围与稳定性 |
必须用目标模型消融验证。
6. 通道级混合精度
少量 Outlier 通道可保留 FP16,其余通道 INT4/INT8,比整层升级更节省。但会引入分支、索引和额外 Kernel。
如果运行时不能融合两路计算,理论内存优势可能换来更高延迟。
7. 激活精度如何选择
权重量化静态且易校准,激活随输入变化更大。W4A16 风险通常低于 W4A8,但 Prefill 计算收益也可能较少。
动态激活量化按请求计算 Scale,适应分布但增加开销;静态 Scale 快但对长尾更敏感。
8. KV Cache 是否纳入配置
KV 精度影响长上下文容量与 Attention 质量,可与权重精度独立设置。高风险或超长请求可路由到高精度 KV。
配置需要明确 W/A/KV 三部分,不能只写“INT4 模型”。
9. 精度转换有什么代价
相邻算子位宽不同会产生 Cast、反量化和额外显存读写。碎片化配置可能让图编译器无法融合算子。
net_gain = saved_compute_and_bytes - cast_and_dispatch_overhead
减少精度岛数量,优先选择连续层块或硬件原生组合。
10. 硬件约束如何进入搜索
只允许目标 GPU/CPU/NPU 有高效 Kernel 的位宽与形状。某层理论适合 INT4,但设备需回退 FP16,就不应作为有效候选。
搜索成本函数使用实测或可靠 Lookup Table,而不是只按参数位数估计延迟。
11. 校准集怎样设计
覆盖语言、任务、长度、格式和安全长尾,记录层级激活统计。敏感度排序可能随校准分布变化。
用独立验证集选择配置,避免同时用一批数据估 Scale、挑位宽又报告最终结果。
12. 如何做自动精度分配
对每个模块预计算不同位宽的质量损失与资源收益,再用贪心/动态规划在预算下选择;最后对组合微调或 QAT。
层间交互使可加性假设不完全成立,因此自动结果仍需端到端验证和局部搜索。
若候选位宽很多,可先限制为少数硬件友好档位,并把转换开销作为边成本;否则算法可能选出纸面资源最优、运行时却充满 Cast 的方案。
13. 如何验收和上线
报告通用与长尾任务、安全、校准、Schema/工具成功率;性能测真实 Batch、长度和硬件上的显存、TTFT、TPOT、吞吐和功耗。
灰度按 quant_config 标记,保留高精度版本回滚。模型或硬件变化后重新搜索,不能永久复用旧配置。
混合精度的价值,是把有限高精度预算用在真正敏感且硬件能够高效执行的位置。
14. 常见误区与追问
- 误区:首尾层永远必须 FP16。 常见经验不等于所有模型结论。
- 误区:层级 Loss 可简单相加。 层间误差会交互。
- 误区:位宽越碎越接近最优。 Cast 和 Kernel 碎片会拖慢。
- 误区:只量化权重就能称 INT4 推理。 激活和 KV 精度也要说明。
- 误区:参数量可准确预测延迟。 硬件 Kernel 与数据搬运更关键。
- 追问:怎样找敏感层? 逐层消融结合激活/Hessian,再做任务验证。
- 追问:何时用 QAT? 极低位宽且 PTQ 混合精度仍达不到质量时。
15. 加强记忆
- 先做两端基线:FP16 与统一低比特。
- 再测敏感度:消融、Outlier、梯度/Hessian。
- 再分预算:质量约束下分配 FP16/INT8/INT4。
- 再看全链路:权重、激活与 KV 分开说明。
- 再减转换:少量连续精度岛、硬件原生 Kernel。
- 再做搜索:资源 Lookup 加端到端验证。
- 最后灰度:长尾与安全通过且性能真实兑现。