27届大模型面试准备(十九):模型量化全攻略——INT8/INT4、GPTQ、AWQ、SmoothQuant 与 KV Cache 量化

27届大模型面试准备(十九):模型量化全攻略------INT8/INT4、GPTQ、AWQ、SmoothQuant 与 KV Cache 量化

上一篇《LoRA 与 PEFT 全攻略》讲的是"怎么用最少的可训练参数把模型调好",属于训练侧省显存。这一篇转到部署侧的省显存主线------量化(Quantization)。它和第十五篇《高效推理全攻略》是一对:那篇讲的是"调度和算子怎么快",这篇讲的是"数字表示怎么小"。量化几乎是所有推理面试的必问题,因为它同时牵扯数值分析、硬件指令集和工程权衡三层。本文按"为什么要量化 → 量化的数学 → PTQ 三大流派(GPTQ / AWQ / SmoothQuant)→ QAT → KV Cache 量化 → 落地选型与踩坑"的顺序展开,每节都给原理、公式骨架、代码片段,结尾给面试速答和高频追问清单。


一、先算一笔账:为什么必须量化

面试官问"为什么要量化",只回答"为了省显存"会显得很浅。真正的答案有三层,而且要能当场算出来。

1.1 显存账

一个 70B 参数的模型,权重按不同精度存储所需显存:

精度 每参数字节 70B 权重显存 能否单卡 A100-80G
FP32 4 280 GB 不能
FP16 / BF16 2 140 GB 不能
INT8 1 70 GB 勉强(无余量给 KV Cache)
INT4 0.5 35 GB 可以,还剩 45G 给 KV Cache

这张表要能脱口而出。结论:INT4 是"70B 单卡可跑"的分水岭,这就是 INT4 量化在社区如此流行的直接原因。

1.2 带宽账(更关键,但常被忽略)

LLM 的 decode 阶段是**访存密集(memory-bound)**而非计算密集。每生成一个 token,都要把全部权重从 HBM 读进片上,算力其实是闲着的。

复制代码
Roofline 视角:decode 阶段单 token 的算术强度
  计算量 ≈ 2 × N_params  FLOPs      (每个参数一次乘一次加)
  访存量 ≈ N_params × bytes_per_param

  算术强度 = 2 / bytes_per_param
    FP16: 2/2 = 1   FLOP/Byte
    INT8: 2/1 = 2   FLOP/Byte
    INT4: 2/0.5 = 4 FLOP/Byte

  A100 的 ridge point ≈ 312 TFLOPS / 2 TB/s ≈ 156 FLOP/Byte
  → 1、2、4 都远低于 156,说明 decode 彻底卡在带宽上

所以有个重要推论:decode 阶段的速度近似与"权重字节数"成反比。FP16 换 INT4,权重体积减 4 倍,理论 decode 吞吐能提升接近 4 倍------这个提升不是来自算得快,而是来自读得少。这是面试的高分回答点。

1.3 成本账

显存小了,同一张卡就能塞更大的 batch 和更长的 KV Cache,单位 token 成本随之下降。量化本质上是在"精度损失"和"服务成本"之间做交易。

复制代码
                 量化带来的三重收益
    ┌─────────────┬─────────────┬──────────────┐
    │  显存下降    │   带宽下降   │  batch 变大   │
    │  4x (INT4)  │   4x        │  吞吐再上升   │
    └──────┬──────┴──────┬──────┴──────┬───────┘
           └─────────────┴─────────────┘
                    单 token 成本 ↓↓
                         代价:精度损失(可控)

二、量化的数学骨架

2.1 均匀仿射量化

主流量化都是均匀量化(uniform quantization) ,核心两个参数:缩放因子 scale(s)和零点 zero-point(z)。

复制代码
量化:   q = clamp( round(x / s) + z,  q_min,  q_max )
反量化: x̂ = s × (q - z)

其中对 INT8 对称量化:z = 0q ∈ [-128, 127];INT8 非对称量化:z ≠ 0q ∈ [0, 255]

scale 的取法(min-max 校准):

复制代码
对称:   s = max(|x|) / (2^(b-1) - 1)          # b=8 → 127
非对称: s = (max(x) - min(x)) / (2^b - 1)
        z = round(-min(x) / s)

一段可直接跑的实现:

python 复制代码
import torch

def quantize_tensor(x: torch.Tensor, num_bits: int = 8, symmetric: bool = True):
    """返回 (q, scale, zero_point)。symmetric=True 时 zero_point 恒为 0。"""
    qmax = 2 ** (num_bits - 1) - 1 if symmetric else 2 ** num_bits - 1
    qmin = -(2 ** (num_bits - 1)) if symmetric else 0

    if symmetric:
        scale = x.abs().max() / qmax
        zp = torch.tensor(0, dtype=torch.int32)
    else:
        scale = (x.max() - x.min()) / (qmax - qmin)
        zp = torch.round(qmin - x.min() / scale).to(torch.int32)

    scale = torch.clamp(scale, min=1e-8)
    q = torch.clamp(torch.round(x / scale) + zp, qmin, qmax)
    return q.to(torch.int8), scale, zp


def dequantize_tensor(q, scale, zp):
    return (q.to(torch.float32) - zp) * scale

2.2 量化粒度:per-tensor / per-channel / per-group

这是面试高频追问点。粒度越细,误差越小,但元数据(scale)开销越大。

复制代码
权重矩阵 W  [out_features, in_features]

per-tensor    : 整个 W 共用 1 个 scale        ------ 最省,误差最大
per-channel   : 每个 out_channel 一个 scale   ------ 常用于 INT8 权重
per-group(g=128): 每 128 个输入维度一组 scale  ------ INT4 标配(GPTQ/AWQ 默认)

  in_features = 4096, group_size = 128
  → 每个输出通道有 4096/128 = 32 个 scale
  → 额外开销: 32 × 2 bytes(FP16) / (128 × 0.5 bytes) = 每权重多 ~1 bit
  → 所以说"INT4 group-128"的等效位宽约 4.25 bit

结论要背下来:INT8 用 per-channel 就够;INT4 必须用 per-group(通常 g=128),否则精度崩

2.3 W8A8 / W4A16 命名法

W 指权重(weight),A 指激活(activation)。

方案 含义 典型代表 适用场景
W8A8 权重和激活都 INT8 SmoothQuant、LLM.int8() 追求吞吐,prefill 计算受益大
W4A16 权重 INT4,激活仍 FP16 GPTQ、AWQ 追求显存和 decode 速度
W4A8 权重 INT4,激活 INT8 QoQ、部分定制方案 极致压榨,工程复杂
W8A16 权重 INT8,激活 FP16 bitsandbytes LLM.int8() 保精度,实现简单
FP8 (E4M3/E5M2) 浮点 8 位 H100 原生支持 精度最好的 8 位方案

关键判断:W4A16 只解决带宽问题,不解决算力问题------因为算之前要把 INT4 反量化回 FP16 再做 GEMM。所以 W4A16 对 decode(带宽瓶颈)提升巨大,对 prefill(算力瓶颈)几乎没提升,甚至因为反量化开销略慢。这个反直觉的点是面试区分度极高的答案。


三、量化难在哪:激活值的离群点

如果量化只是简单地缩放取整,就不会有这么多论文。真正的难点是 LLM 激活值中存在系统性离群点(outlier)

复制代码
某层 hidden_states 的分布示意(4096 维)

  绝大多数通道:  |x| ∈ [0, 3]
  少数几个通道:  |x| ∈ [50, 100]   ← outlier channel,固定出现在特定维度

  若 per-tensor 量化:
    scale = 100 / 127 ≈ 0.787
    → 值为 0.5 的正常激活量化后 = round(0.5/0.787) = 1
    → 反量化回来 = 0.787,误差 57%!大量小信号被压成 0 或 1

这就是 LLM.int8() 论文的核心发现:当模型参数超过约 6.7B 时,会稳定出现幅值极大的离群特征维度,且这些维度对模型效果至关重要,直接裁掉会导致性能崩溃。

三种应对思路,正好对应后面三个流派:

复制代码
   离群点问题
        │
        ├── 思路A:把离群点单独拎出来算  → LLM.int8() 混合精度分解
        ├── 思路B:把难度从激活转移到权重 → SmoothQuant 数学等价缩放
        └── 思路C:干脆不量化激活,只量化权重,
                   但按激活重要性保护关键权重 → AWQ / GPTQ

四、PTQ 三大流派详解

PTQ(Post-Training Quantization,训练后量化)不需要重训,是工业界绝对主流。

4.1 LLM.int8():混合精度分解

最朴素也最好懂的方案。做法:把激活中超过阈值(通常 6.0)的离群通道挑出来,用 FP16 算;其余通道走 INT8。

复制代码
X [batch, 4096]  ×  W [4096, 11008]

  1) 找出 X 中 |x| > 6.0 的列索引集合 O(通常 |O| < 10)
  2) 拆分:
     X_out = X[:, O]      (FP16)     W_out = W[O, :]      (FP16)
     X_int = X[:, ~O]     (INT8)     W_int = W[~O, :]     (INT8)
  3) Y = X_out @ W_out  +  dequant(X_int @ W_int)

优点:几乎零精度损失,实现简单(bitsandbytes 一行 load_in_8bit=True)。

缺点:。因为要动态检测离群点、拆分张量、跑两次 GEMM 再相加,实际吞吐往往比 FP16 还低。所以它适合"显存不够但不追求速度"的场景(比如本地跑大模型做实验),不适合线上服务。这个"能省显存但更慢"的坑必须记住。

4.2 SmoothQuant:把量化难度从激活转移到权重

核心洞察非常优雅:激活难量化(有离群点),权重好量化(分布平坦)。那能不能在数学上等价地把一部分"难度"从激活挪给权重

复制代码
原式:  Y = X · W

引入对角缩放矩阵 diag(s):
       Y = (X · diag(s)^-1) · (diag(s) · W)
           └──── X̂ ────┘   └──── Ŵ ────┘

  X̂ 的离群点被 s 除小了 → 好量化了
  Ŵ 被 s 乘大了一点     → 稍微难量化,但权重本来余量足

缩放因子的取法引入超参 α(migration strength,通常 0.5):

复制代码
s_j = max(|X_j|)^α / max(|W_j|)^(1-α)

  α = 0   → 全部难度留在激活(等于不做)
  α = 1   → 全部难度推给权重(权重会崩)
  α = 0.5 → 两边均分,实践最优

关键点:diag(s)^-1 可以被融合进上一层的 LayerNorm 或前一个线性层的权重里,推理时零额外开销。这是它比 LLM.int8() 快的根本原因。

python 复制代码
@torch.no_grad()
def smooth_ln_linear(ln, linears, act_scales, alpha=0.5):
    """把 LayerNorm 后面的若干 Linear 一起做 SmoothQuant 平滑。
    act_scales: 校准得到的每通道激活最大绝对值 [hidden]"""
    device, dtype = linears[0].weight.device, linears[0].weight.dtype
    act_scales = act_scales.to(device=device, dtype=dtype)

    # 权重侧每通道最大值:对所有共享输入的 linear 取并集
    w_scales = torch.cat(
        [fc.weight.abs().max(dim=0, keepdim=True)[0] for fc in linears], dim=0
    ).max(dim=0)[0].clamp(min=1e-5)

    s = (act_scales.pow(alpha) / w_scales.pow(1 - alpha)).clamp(min=1e-5)

    # 难度迁移:LN 除以 s(等价于激活除以 s),Linear 权重乘以 s
    ln.weight.div_(s)
    if getattr(ln, "bias", None) is not None:
        ln.bias.div_(s)
    for fc in linears:
        fc.weight.mul_(s.view(1, -1))

SmoothQuant 是 W8A8 方案,因此它对 prefill 阶段(计算密集)有真实的算力加速------INT8 Tensor Core 吞吐是 FP16 的 2 倍。这一点和 W4A16 形成鲜明对比。

4.3 GPTQ:基于二阶信息的逐层误差补偿

GPTQ 走的是另一条路:只量化权重(W4A16),但量化时不是简单取整,而是逐列量化并把误差补偿到还没量化的列上

它的理论基础是 OBQ(Optimal Brain Quantization),目标是最小化每层输出的重建误差:

复制代码
目标:  argmin_Ŵ  || X·W - X·Ŵ ||²_F

用二阶泰勒展开,海森矩阵 H = 2·X^T·X
量化第 q 列后,对剩余列的最优补偿量:

    δ_rest = - ( w_q - quant(w_q) ) / [H^-1]_qq  ×  [H^-1]_{q, rest}

直观理解:"这一列我取整取多了,那就让后面还没量化的列少一点,把整体输出拉回来。" 这是一种贪心的误差重分配。

算法骨架:

python 复制代码
# GPTQ 单层量化的核心循环(简化版,省略 Cholesky 与分块细节)
def gptq_quantize_layer(W, H_inv, group_size=128, bits=4):
    """W: [out, in],H_inv: [in, in] 海森逆的 Cholesky 上三角"""
    Q = torch.zeros_like(W)
    for i in range(W.shape[1]):                 # 按输入维度逐列
        w = W[:, i].clone()
        d = H_inv[i, i]

        if i % group_size == 0:                 # 每组重新算 scale
            scale, zp = find_params(W[:, i:i + group_size], bits)

        q = quantize_column(w, scale, zp, bits) # 取整
        Q[:, i] = q
        err = (w - dequant(q, scale, zp)) / d   # 归一化误差

        # 关键:把误差按海森逆的相关性补偿给后面所有未量化列
        W[:, i + 1:] -= err.unsqueeze(1) @ H_inv[i, i + 1:].unsqueeze(0)
    return Q

工程要点:

  • 需要少量校准数据(通常 128 条、每条 2048 token)来估计 H = X^T X

  • 海森矩阵可能奇异,实践中要加阻尼 H += λ·mean(diag(H))·I,λ 取 0.01。

  • 采用"分块 + 惰性更新"(block size 128)避免逐列更新的巨大访存开销,这是 GPTQ 相对 OBQ 能跑得动 175B 的工程关键。

  • 单卡量化 70B 大约 1~4 小时。

4.4 AWQ:按激活幅值保护关键权重

AWQ(Activation-aware Weight Quantization)的核心观察比 GPTQ 更简洁:并非所有权重同等重要,只有约 1% 的"显著权重"决定了模型效果,而判断显著性的依据不是权重自身大小,而是对应的激活幅值大小

论文里的消融实验很有说服力:

保护策略 INT3 下的 PPL
不保护(全量化) 显著劣化
按权重幅值挑 1% 保 FP16 几乎无改善
按激活幅值挑 1% 保 FP16 大幅改善,接近 FP16

但"混合精度保留 1% FP16"对硬件不友好(不规则内存访问)。AWQ 的巧思是:用逐通道缩放来等价实现"保护",而不真的保留 FP16

复制代码
对显著通道 j 的权重先放大 s 倍,量化后再在激活侧除回来:

    Ŵ_j = quant(W_j · s_j)      Y = (Ŵ_j / s_j) · X_j

  放大后,W_j 在量化格点上占的相对误差变小 → 等效精度更高
  s 的搜索:s = (mean|X_j|)^α,网格搜 α ∈ [0,1] 取重建误差最小

GPTQ vs AWQ 对比(面试必问):

维度 GPTQ AWQ
核心思想 二阶误差补偿 激活感知的通道缩放
是否改权重数值 是(补偿会改后续列) 是(等价缩放)
校准数据依赖 较强,可能过拟合校准集 较弱,泛化更好
量化耗时 慢(小时级) 快(分钟级)
推理速度 相当 略快(kernel 更规整)
精度 相当,个别任务 AWQ 更稳 相当,长尾/多语言场景更稳

一句话总结选型:追求快速量化和跨域泛化选 AWQ;已有成熟 GPTQ 流水线且校准数据贴合业务分布,GPTQ 也够用。目前社区(vLLM、SGLang)对两者支持都很完善。


五、QAT:量化感知训练

PTQ 在 INT4 以下(INT3/INT2)会明显掉点,这时需要 QAT(Quantization-Aware Training)------训练时就模拟量化误差。

核心是 伪量化节点(fake quant)+ 直通估计器(STE)

复制代码
前向: x̂ = dequant(quant(x))       # 引入真实的取整误差
反向: ∂L/∂x = ∂L/∂x̂ · 1{qmin ≤ x/s ≤ qmax}
              └──── STE:round 的梯度直接当作 1 ────┘
python 复制代码
class FakeQuant(torch.autograd.Function):
    @staticmethod
    def forward(ctx, x, scale, qmin, qmax):
        ctx.save_for_backward(x, scale)
        ctx.qmin, ctx.qmax = qmin, qmax
        q = torch.clamp(torch.round(x / scale), qmin, qmax)
        return q * scale

    @staticmethod
    def backward(ctx, g):
        x, scale = ctx.saved_tensors
        # STE + 截断区间外梯度置零
        mask = ((x / scale) >= ctx.qmin) & ((x / scale) <= ctx.qmax)
        return g * mask, None, None, None

现实中大模型很少做全量 QAT(太贵),主流是 QLoRA 式的"量化基座 + LoRA 微调"------基座冻结在 NF4,只训 LoRA。这在第十八篇已详细讲过,两篇可以串起来回答:"QLoRA 本质是 PTQ 之后用 PEFT 把损失补回来,比真 QAT 便宜两个数量级。"


六、KV Cache 量化:长上下文场景的胜负手

权重量化解决的是"模型多大",但长上下文场景下,KV Cache 才是显存大头

复制代码
KV Cache 显存 = 2 × L × H_kv × d_head × S × B × bytes

  以 Llama-3-70B (L=80, H_kv=8 GQA, d_head=128) 为例
  batch=32, seq=32768, FP16:
    2 × 80 × 8 × 128 × 32768 × 32 × 2 B ≈ 343 GB   ← 比 140G 权重还大!
  改 INT8: 171 GB      改 INT4: 86 GB

所以在长上下文 + 大 batch 场景,KV Cache 量化的收益比权重量化更大

实践要点:

  1. K 和 V 要区别对待 。K 有明显的通道级离群点(因为要和 Q 做点积、且叠加了 RoPE),V 的分布更平坦。因此常见做法是 K 用 per-channel 量化,V 用 per-token 量化

  2. 保留最近若干 token 为 FP16 (residual window,如最近 128 个),因为新 token 对注意力贡献最敏感。

  3. INT8 KV Cache 基本无损,可放心上;INT4 KV Cache 在长文本检索类任务(大海捞针)上会掉点,要实测。

  4. vLLM 中开启方式:--kv-cache-dtype fp8(H100 上 FP8 KV 比 INT8 精度更好且有原生支持)。

python 复制代码
# per-token 量化 V(每个 token 一个 scale),比 per-tensor 稳很多
def quant_kv_per_token(v: torch.Tensor, bits=8):
    """v: [B, H, S, D] → 沿最后一维求 scale,每个 (b,h,s) 一个 scale"""
    qmax = 2 ** (bits - 1) - 1
    scale = v.abs().amax(dim=-1, keepdim=True) / qmax   # [B,H,S,1]
    scale = scale.clamp(min=1e-8)
    q = torch.clamp(torch.round(v / scale), -qmax - 1, qmax).to(torch.int8)
    return q, scale

七、落地选型与真实踩坑

7.1 决策树

复制代码
                     要不要量化?
                          │
           显存够 & 延迟达标 ──否──> 直接 FP16/BF16,别自找麻烦
                          │是(显存/成本有压力)
                          ▼
            主要瓶颈是 decode 还是 prefill?
                 │                      │
             decode(生成长)          prefill(输入长/高并发)
                 │                      │
            W4A16 (AWQ/GPTQ)      W8A8 (SmoothQuant) 或 FP8
                 │                      │
                 └──── 长上下文?────────┘
                          │是
                     叠加 KV Cache 量化 (FP8/INT8)
                          │
                     精度不达标?
                          │是
              放宽到 INT8 权重,或 QLoRA 补偿微调

7.2 五个真实踩坑

坑一:只看 PPL 不看下游任务。 PPL 掉 0.1 看起来无所谓,但代码生成、数学推理、工具调用这类任务对量化极度敏感,可能掉 5~10 个点。评测必须覆盖真实业务任务,尤其是 JSON 结构化输出的合法率------量化后模型漏引号、括号不配对的概率会上升,这在 Agent 场景是致命的。

坑二:校准集选错。 GPTQ 用 wikitext 校准、却上线跑中文客服,分布不匹配会明显掉点。校准集应该从线上真实流量采样 128~512 条,这是成本极低、收益极大的一步。

坑三:以为 INT4 一定比 INT8 快。 前面算过,W4A16 在 prefill 阶段因为要反量化,可能比 W8A8 更慢。高并发短输出场景,W8A8 往往才是对的。

坑四:忽略 lm_head 和 embedding。 词表 15 万、hidden 8192 的 lm_head 就有 12 亿参数,占比不小;但它对量化敏感(直接决定输出分布)。通用做法是 lm_head 保持 FP16 不量化,其余全量化。

坑五:group_size 和硬件对不齐。 group_size 必须能被 kernel 的 tile 尺寸整除,随手改成 64 或 100 可能导致 kernel fallback 到极慢的通用实现。没有充分理由就用默认的 128

7.3 一段可直接用的 vLLM 部署示例

bash 复制代码
# AWQ INT4 权重 + FP8 KV Cache,长上下文高吞吐配置
python -m vllm.entrypoints.openai.api_server \
  --model /models/Llama-3-70B-Instruct-AWQ \
  --quantization awq_marlin \
  --kv-cache-dtype fp8 \
  --max-model-len 32768 \
  --gpu-memory-utilization 0.92 \
  --tensor-parallel-size 2

注意 awq_marlin 而不是 awq:Marlin 是专门优化的 W4A16 kernel,在 Ampere/Hopper 上比原始 AWQ kernel 快约 1.5~2 倍,能用就一定要用。


八、面试速答

Q:量化为什么能加速推理?

A:LLM 的 decode 阶段是访存密集型,每生成一个 token 都要把全部权重从 HBM 读一遍,算力是闲置的。量化把权重字节数减少 N 倍,访存量就减少 N 倍,decode 吞吐近似提升 N 倍。所以加速主要来自"读得少"而非"算得快"。但 prefill 是计算密集型,W4A16 因为需要反量化反而可能变慢,只有 W8A8/FP8 这类激活也量化的方案才能吃到 INT8 Tensor Core 的算力红利。

Q:LLM 量化最大的技术难点是什么?

A:激活值的系统性离群点。模型超过约 6.7B 后会稳定出现少数幅值极大(50~100 倍于常规值)的特征维度,且这些维度对效果至关重要。用 per-tensor 量化时,这些离群点会把 scale 撑大,导致绝大多数正常激活被压缩到极少的量化格点上,误差急剧放大。三种解法分别是 LLM.int8() 的混合精度分解、SmoothQuant 的难度迁移、AWQ/GPTQ 的只量化权重加重要性保护。

Q:GPTQ 和 AWQ 的区别?

A:GPTQ 基于二阶海森信息做逐列量化和误差补偿,把当前列的取整误差按相关性分摊给尚未量化的列,理论性强但量化慢(小时级)且对校准集分布较敏感。AWQ 基于"激活幅值大的通道对应的权重更重要"这一观察,通过逐通道缩放等价地保护关键权重,量化快(分钟级)、跨域泛化更好、kernel 更规整。精度上二者接近,工程上我倾向优先试 AWQ。

Q:什么是 W4A16、W8A8?分别适合什么场景?

A:W 是权重位宽,A 是激活位宽。W4A16 只压权重,收益在显存和带宽,适合长文本生成、显存吃紧、追求 decode 速度的场景,代表是 GPTQ/AWQ。W8A8 权重激活都压到 INT8,能真正调用 INT8 Tensor Core,对 prefill 这种计算密集阶段有实际算力加速,适合高并发短输出场景,代表是 SmoothQuant。H100 上还可以用 FP8,动态范围比 INT8 大,精度更好且硬件原生支持。

Q:SmoothQuant 的原理?为什么它不增加推理开销?

A:它利用 Y = (X·diag(s)^-1)·(diag(s)·W) 的数学等价性,把激活的量化难度按 s_j = max|X_j|^α / max|W_j|^(1-α)(α 通常 0.5)迁移一部分到权重上,让两边都变得好量化。之所以零开销,是因为 diag(s)^-1 这个缩放可以在离线阶段直接融合进前一层的 LayerNorm 权重或线性层权重里,推理时没有任何额外算子。

Q:INT4 量化为什么必须用 group-wise?

A:INT4 只有 16 个量化格点,表达能力极其有限。如果整个张量或整个通道共用一个 scale,一旦范围内有较大值,小值就会被大量压成同一个格点,信息损失严重。按 128 个输入维度分组各自算 scale,能让每组的动态范围贴合局部分布。代价是每 128 个 4-bit 权重要多存一个 FP16 scale(和 zero point),等效位宽从 4 升到约 4.25,这个开销完全值得。

Q:KV Cache 要不要量化?

A:长上下文加大 batch 时必须量化。70B 模型在 batch=32、seq=32K 下 KV Cache 能到 343GB,比 140GB 的权重还大,这时 KV 量化的收益远超权重量化。实践上 INT8/FP8 基本无损可以放心上;INT4 在大海捞针类长程检索任务上会掉点需要实测。工程细节是 K 和 V 要分开处理------K 因为叠加 RoPE 且要做点积,存在通道级离群点,宜用 per-channel;V 分布平坦,per-token 即可;另外保留最近 128 个 token 为高精度会更稳。

Q:量化后如何验证效果?

A:三层验证。第一层是 PPL(wikitext/c4)做快速冒烟,只能判断"有没有崩"。第二层是标准 benchmark(MMLU、GSM8K、HumanEval),重点看推理和代码这类对量化敏感的任务。第三层也是最重要的一层,是业务真实数据的端到端评测,Agent 场景还要专门统计 JSON 结构化输出合法率和工具调用参数准确率------量化后这两个指标的劣化往往比 PPL 明显得多,而它们直接决定线上能不能用。


九、高频追问清单

  1. 为什么模型规模超过 6.7B 后离群点问题突然变严重?和涌现现象有关系吗?
  2. GPTQ 的海森矩阵为什么可以用 X^T X 近似?阻尼系数的作用是什么?
  3. AWQ 论文中"按权重幅值挑 1% 保 FP16 几乎无效,按激活幅值挑就有效",如何解释?
  4. NF4(NormalFloat4)和普通 INT4 的区别?它的信息论依据是什么?
  5. 为什么 lm_head 通常不量化?如果一定要量化会有什么现象?
  6. FP8 的 E4M3 和 E5M2 分别用在哪?为什么前向用 E4M3、反向梯度用 E5M2?
  7. Marlin kernel 为什么比朴素 W4A16 kernel 快这么多?它做了哪些优化?
  8. 量化和 MoE 一起用有什么特殊问题?专家权重量化的难点在哪?
  9. 如果线上发现量化模型在某类 badcase 上明显劣化,你的排查路径是什么?
  10. 量化会不会放大模型的安全风险(比如更容易被越狱)?为什么?

下一篇(A20)会讲大模型评测体系------量化后"到底掉了多少点"这个问题,最终要靠一套可信的评测体系来回答。从标准 benchmark 的局限、数据污染的检测,到 LLM-as-Judge 的偏差校正和 Arena 式对战评测,把"怎么科学地说模型好不好"讲清楚。

相关推荐
深圳市快瞳科技有限公司2 小时前
个体识别、行为解读、健康管理:多模态宠物AI大模型的场景化落地
人工智能·算法·计算机视觉·大模型·多模态·宠物·宠物ai识别
安逸sgr2 小时前
AI 编程工具在真实项目中适合做什么?不适合做什么?
人工智能·ai·大模型·agent·智能体
thesky1234563 小时前
27届大模型面试准备(二十):评测体系全攻略——Benchmark、数据污染、LLM-as-Judge 与 Arena 对战
大模型·benchmark·模型评测·llm-as-judge·数据污染·elo·mmlu
大鹏的NLP博客3 小时前
大模型 Tokenizer:从字符到 Byte,再到大词表
深度学习·机器学习·大模型·分词
爱笑的k118 小时前
4卡v100显卡坞方案
大模型
CoderJia程序员甲8 小时前
GitHub 热榜项目 - 周榜(2026-08-08)
ai·大模型·github·agent
thesky12345618 小时前
27届大模型面试准备(十六):后训练全攻略——SFT、RLHF、DPO、PPO 一次讲透
大模型·sft·rlhf·ppo·dpo·面试准备·后训练