想象你要搬家。原来每个家具都有独立的原包装箱(FP16),空间很充裕,一个浮点数可以用 16 位存得舒舒服服。但新家的储物空间只有原来的四分之一(INT4),你必须把所有家具重新压缩打包。直接硬塞,家具必然磕碰变形;聪明的搬家师傅会先测量每个区域能承受的重量,把一个家具压紧后,如果旁边空出了一点,就顺手把隔壁家具的位置微调一下,让整面墙看起来依然严丝合缝。这就是 GPTQ 在做的事:它把“压缩大模型的每一层”看作一次精密的搬家打包——用 Hessian 矩阵当“承重地图”找出哪里不能碰、哪里可以挪,再把压缩造成的误差顺着承重关系分摊给邻居权重,最终在 INT4 下依然保持接近 FP16 的输出质量。空间省出来了,家具还都能用,这正是量化压缩的最高境界。

岗位关联

一句话价值:掌握 GPTQ 分组量化与误差补偿,你就能在显存不够、算力吃紧的部署场景中,把几十 GB 的大模型压到四分之一体积还保住精度——这是当前端侧部署最硬核的实用技能之一。

目录
  1. 可视化演示
  2. 量化基础概念
  3. 误差度量原理
  4. Hessian逆矩阵
  5. 分组量化策略
  6. GPTQ算法流程
  7. 部署价值与挑战
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示GPTQ逐层量化流程、Hessian误差补偿机制及分组量化策略,直观理解INT4压缩如何在保持精度的同时降低模型体积。

本节配有交互动效(进入视口后自动加载,约 3KB)。

GPTQ逐层量化流程 逐层计算Hessian并量化权重列 用Hessian逆补偿剩余权重减小误差 argmin ‖WX−Q(X)‖² 最小化量化前后输出误差

量化基础概念

新家空间只有原来的四分之一,师傅掏出真空压缩袋。原本每个参数都占 16 格抽屉(FP16),现在只能给 4 格抽屉(INT4)。4 格抽屉只有 16 种状态(2 的 4 次方),而一个浮点数本来有无数种取值,现在只能“就近塞进”16 个格子之一。这就是量化最朴素的样子:把连续的浮点数字,投射到离散的整数盒子里。

要让这个投射尽可能公平,需要定两把尺子:缩放因子 s(每个整数代表多大的浮点跨度)和零点 z(整数坐标轴的偏移)。有了它们,0.7321 这样的数会被映射成整数 5 或 6,反量化时再乘回 s、减去 z,得到约 0.7031 或 0.8594。跟原值一比,差的那一点,就是量化误差。

量化误差从哪来?一是表示范围有限,超出区间的极端值被生硬截断;二是格子太大,落在格子中间的小数只能四舍五入。误差有多大,直接决定模型输出会不会走样,这也是后面所有精密补偿要解决的问题。

压缩袋把羽绒服压扁了,但保暖性还在;如果压缩袋尺寸不合适,拉链就拉不上——对应极端权重没处放。所以,量化的第一步,就是找到合身的袋子。

q=⌊rs⌉+zq = \left\lfloor \frac{r}{s} \right\rceil + z
这个公式像“真空压缩袋的刻度换算”:把所有浮点物品按统一比例尺压进 0~15 的整数格子。
  1. 原始值$r$ 是待量化的浮点权重,比如 0.7321,它带着丰富的小数信息,但 INT4 世界里没有这么细的格子。
  2. 缩放因子$s$ 是比例尺,由这组权重的最大值和最小值决定,它把浮点区间压到 $0 \sim 15$ 的整数区间。
  3. 就近取整$\lfloor \cdot \rceil$ 表示四舍五入到最近的整数,落在这个步骤会丢掉小数部分,这是量化误差的第一来源。
  4. 零点偏移$z$ 让最小浮点值映射到整数 0,避免负数被截断,保证整数空间被充分利用。

误差度量原理

师傅不会凭感觉说“压得还不错”,而是拿出搬家前后的对比照片逐件检查:沙发还能不能坐、桌子稳不稳。GPTQ 的“对比照片”是量化前后整个层的输出——它不关心权重本身变没变形,只关心最终输出差别大不大。这个思路非常重要:权重变了一点没关系,只要模型的回答依然靠谱就行。

技术地讲,设该层原始权重为 $W$,量化造成的权重改动为 $\delta$,输入激活为 $X$(从校准数据里采样一小批样本)。量化前后的输出分别是 $WX$ 和 $(W + \delta)X$。GPTQ 的优化目标,就是找一个最小的 $\delta$,让这两个输出矩阵每个元素的误差平方和最小。

更妙的是,用泰勒展开还能预判:如果我们对权重施加扰动 $\delta$,损失变化量约等于一阶梯度项加上 $\frac{1}{2}\delta^{T}H\delta$。对于“让输出不变”这个目标来说,主要盯住二阶项就够——这为后面的 Hessian 矩阵埋下了伏笔。

误差度量相当于搬家验收清单,量的是“功能是否完好”,不是“外形是否一致”。有了这张清单,师傅才知道当前压缩方案离完美还差多少。

δ∗=arg⁡min⁡δ∥WX−(W+δ)X∥F2\delta^{*} = \mathop{\arg\min}_{\delta} \left\| WX - (W + \delta) X \right\|_F^2
这是“搬家验收单”的数学版:谁的入住体验最接近原样,谁的打包方案就最好。
  1. 原始输出$WX$ 表示量化前该层的输出,是“搬家前使用体验”的基准。
  2. 扰动输出$(W + \delta)X$ 表示权重被改动后该层的输出,我们希望它跟基准尽量一致。
  3. 误差平方和$\| \cdot \|_F^2$ 逐个元素计算两个输出矩阵差值的平方和,相当于验收单上所有项目的总失分。
  4. 最优解$\delta^{*} = \mathop{\arg\min}$ 遍历所有可能的权重修正,挑出总失分最小的那种修正方式。

Hessian逆矩阵

有了验收清单,师傅还需要一张承重地图:知道哪面墙不能拆、哪面墙可以微调。这张地图就是 Hessian 矩阵。它由输入激活算出来:$H \approx 2XX^{T}$。矩阵对角线上的元素告诉每个权重有多“敏感”——一碰就坏的承重墙;非对角线元素告诉权重之间相互影响——墙和墙之间的连接关系。

当量化到第 $q$ 列权重时,它的取值从浮点 $w_q$ 变成格点 $\hat{w}_q$,产生误差 $e = w_q - \hat{w}_q$。如果只是硬着头皮接受这个误差,输出就会偏;GPTQ 的聪明之处在于,把这个误差“分摊”到还没量化的列 $F$ 上,让它们各自做出微小调整把误差吸收掉。调整的方向和幅度,由 Hessian 逆矩阵的对应元素决定——这就是误差补偿机制。

直觉上:谁的敏感度低,谁就多承担一点补偿;谁的敏感度高,就尽量别动它。这就像搬家时宁可挪一挪不承重的纸箱,也不去碰承重墙。

误差没有神秘消失,它只是从承重墙转移到了纸箱上。对整体结构来说,这已经是最优解。

δF=−wq−w^q[H−1]qq [H−1]F,q\delta_F = -\frac{w_q - \hat{w}_q}{[H^{-1}]_{qq}} \, [H^{-1}]_{F,q}
承重地图让补偿有的放矢:误差没有消失,但它从“敏感的位置”转移到了“不敏感的位置”。
  1. 量化残差$w_q - \hat{w}_q$ 是第 $q$ 列权重量化前后的差值,即“被压缩袋挤压产生的形变量”。
  2. 敏感度分母$[H^{-1}]_{qq}$ 是逆 Hessian 的第 $q$ 个对角元,代表这个位置的“扛压能力”,它越小说明越扛得住改动。
  3. 补偿强度$-\frac{w_q - \hat{w}_q}{[H^{-1}]_{qq}}$ 决定邻居要吸收多少形变,敏感度低的邻居多承担一点。
  4. 补偿方向$[H^{-1}]_{F,q}$ 把形变量按相关性散布到所有未量化列 $F$ 上,就像沿着受力线把力卸到周边。

分组量化策略

如果师傅把整屋家具当成一个整体来压缩,一床席梦思和一把折叠椅混在一起,压缩袋必然迁就最大的那个,导致大部分家具都被压得很难受。聪明的做法是分区打包:卧室归卧室、客厅归客厅,每区用独立尺寸的箱子。

分组量化正是这个思路:把权重矩阵按通道方向分成小组,比如每 128 个通道为一组(group_size=128)。每组独立计算自己的缩放因子 $s_g$ 和零点 $z_g$,组与组之间互不干扰。这样,如果某一组里出现了极端异常值,它只影响自己所在的组,不会带偏全局的尺子。

这里有一个权衡:组越小,缩放因子越多,拟合越精细,但额外存储开销也越大;组越大,参数开销小,却容易被异常值污染。GPTQ 在实践中最常用的就是 group_size=128 或 64,在精度和压缩率之间取得平衡。

分区打包让每组都有合身的箱子,异常值这只“不听话的猫”被单独关进一间房,不会把整个屋子搅乱。分组量化是 GPTQ 在工程上落地的关键一步。

w^ij=sg(⌊wijsg⌉−zg),g=⌊jG⌋\hat{w}_{ij} = s_g \left( \left\lfloor \frac{w_{ij}}{s_g} \right\rceil - z_g \right), \quad g = \left\lfloor \frac{j}{G} \right\rfloor
每个房间都有自己的卷尺,量起来才准——这正是分组量化优于整层统一量化的关键。
  1. 组索引$g = \left\lfloor \frac{j}{G} \right\rfloor$ 由通道序号 $j$ 与组大小 $G$ 决定当前权重属于第几组。
  2. 组内缩放$s_g$ 是第 $g$ 组独立计算的缩放因子,只反映本组权重的取值范围,不被其他组带偏。
  3. 组内零点$z_g$ 是第 $g$ 组的偏移量,让本组最小权重恰好落在整数区间底部。
  4. 重建公式$\hat{w}_{ij} = s_g (\lfloor \frac{w_{ij}}{s_g} \rceil - z_g)$ 从整数还原成近似浮点,组与组之间精度互不影响。

GPTQ算法流程

正式开工。师傅的流程并不复杂:一个房间一个房间收拾——对应 GPTQ 的逐层量化。每层里,一件一件地处理权重,每压好一件家具,就看看周围的家具需不需要挪一挪——对应误差补偿更新,让整面墙始终严丝合缝。

在某一层内部,GPTQ 维护一个 Hessian 逆矩阵,然后反复执行三步操作:选列、量化、补偿。选列时采用贪心策略——优先处理“现在量化最不心疼”的权重列;量化时把它就近取整到整数格点;补偿时用 Hessian 逆更新所有还没量化的列,让它们吸收这次量化产生的误差。每次迭代后,已量化列的误差被摊到未量化列上,所以整个过程是自适应的。

“最不心疼”怎么度量?GPTQ 用一个近似代价公式:该列量化误差的平方,除以两倍的 $[H^{-1}]_{qq}$。代价越小,说明这一列现在量化造成的伤害越小,越适合先处理。这个公式保证了每一步都在聪明地推进。

每放一件家具就微调邻居位置,等房间收拾完,整体墙面依然平整如初——这正是“误差补偿保精度”这七个字的由来。

ℓ(q)=(wq−w^q)22[H−1]qq\ell^{(q)} = \frac{(w_q - \hat{w}_q)^2}{2 [H^{-1}]_{qq}}
每次选择“最不心疼的箱子先压”,把伤害降到最低,再让邻居帮忙擦屁股——这就是贪心加补偿的默契。
  1. 量化代价$(w_q - \hat{w}_q)^2$ 是第 $q$ 列权重量化前后差值的平方,它越大说明这一列丢的信息越多。
  2. 敏感度折算除以 $2[H^{-1}]_{qq}$ 等价于按该位置的“扛压能力”调整代价,这样高敏感度的列不会被鲁莽地先处理。
  3. 迭代选择GPTQ 取 $\ell^{(q)}$ 最小的列先量化,量化后立即更新剩余列,再进入下一轮选择。

部署价值与挑战

箱子终于运到新家。INT4 的箱子只有 FP16 的四分之一,却能装下同样能用的家具。在语言模型的困惑度评测中——“困惑度”可以理解为模型预测下一句时的错愕程度,越低越好——GPTQ 的 INT4 模型与 FP16 的差距通常只有 1%~3%,但模型体积直接砍掉 75%。这意味着曾经需要双卡才能跑的模型,现在单卡甚至手机都能扛下来。

关键收益有两个:一是显存和存储节省约 4 倍,16GB 的 FP16 模型变成约 4GB 的 INT4;二是推理时访存带宽压力减小,同等硬件下批处理量大约也能提升 4 倍,吞吐和延迟双双受益。短板也很明显:极个别敏感层在量化后仍可能出现可感知的退化,因此实际部署常搭配少量校准数据或在关键层保留 FP16,做混合精度保护。

空间省下来的同时功能仍然完好,这正是 GPTQ 一直以来的追求。端侧部署不再是“拆东墙补西墙”,而是真正把大模型塞进小设备的实用方案。

MemINT4=MemFP164,BatchINT4≈4×BatchFP16\text{Mem}_{\text{INT4}} = \frac{\text{Mem}_{\text{FP16}}}{4}, \quad \text{Batch}_{\text{INT4}} \approx 4 \times \text{Batch}_{\text{FP16}}
用最小的箱子装最完整的家:空间省下来,功能还都在。
  1. 位宽比$\frac{16}{4}$ 是 FP16 与 INT4 的位宽之比,它决定了单个参数存储空间压缩到什么程度。
  2. 新显存$\text{Mem}_{\text{INT4}} = \frac{\text{Mem}_{\text{FP16}}}{4}$ 表示同样的模型用 INT4 存储后,显存占用变为四分之一。
  3. 批次提升$\text{Batch}_{\text{INT4}} \approx 4 \times \text{Batch}_{\text{FP16}}$ 在显存受限时,同一张卡能塞进的推理批次约放大 4 倍,吞吐量随之提高。

AI 应用场景

手机端离线大模型助手

阶段:模型部署与推理优化

解决的问题:过去 7B 参数量的大模型 FP16 权重占 14GB 以上,手机内存根本扛不住,只能依赖云端 API,离线就成了奢望。GPTQ 将模型压到 INT4 后体积缩至约 4GB,配合分组量化,手机端也能流畅运行,用户提问时不再需要上传数据,隐私和响应速度同时得到保障。

具体案例:某端侧智能助手 App 把 7B 聊天模型用 GPTQ INT4 量化,模型文件从 14GB 降到 4GB 以内,中端手机也能实时完成对话生成,离线模式下依然保持流畅的日常问答体验。

云GPU集群推理成本优化

阶段:推理服务部署与资源调度

解决的问题:在线服务面对高并发时,显存是硬约束。FP16 模型一张 A100 只能同时服务少数几个请求,成本居高不下。GPTQ 量化后显存占用降为四分之一,同样的卡能塞进约 4 倍的 batch,单位请求的推理成本和延迟同步下降。

具体案例:某 SaaS 公司为开源对话模型做 GPTQ INT4 量化后,将推理服务部署到 A10 卡上,QPS 提升接近 3 倍,单次请求成本下降约 60%,同时通过校准集的数据让模型输出质量几乎无感变化。

Python 演示

python61 行
import numpy as np  def quantize_group(w, bits=4):    """将一组权重线性量化到 bits 位, 返回整数及缩放/零点."""    qmax = 2**bits - 1    wmin, wmax = w.min(), w.max()    if wmax - wmin < 1e-12:        return np.zeros_like(w, dtype=np.int32), 1.0, 0.0    s = (wmax - wmin) / qmax    z = np.round(-wmin / s)    q = np.clip(np.round(w / s) + z, 0, qmax)    return q.astype(np.int32), s, z  def dequantize(q, s, z):    """反量化: 从整数还原回浮点."""    return s * (q - z)  def plain_quantize(W, bits=4):    """朴素方案: 逐列独立量化, 不做任何补偿."""    Wp = np.zeros_like(W, dtype=np.float64)    for c in range(W.shape[1]):        q, s, z = quantize_group(W[:, c], bits)        Wp[:, c] = dequantize(q, s, z)    return Wp  def gptq_layer(W, X, bits=4):    """GPTQ 风格逐列量化 + Hessian 逆误差补偿的教学简化版."""    rows, cols = W.shape    H = 2 * (X @ X.T) + 1e-4 * np.eye(cols)    Hinv = np.linalg.inv(H)    Wq = W.copy().astype(np.float64)     for col in range(cols):        w = Wq[:, col]        q, s, z = quantize_group(w, bits)        dq = dequantize(q, s, z)        err = dq - w        if col < cols - 1 and abs(Hinv[col, col]) > 1e-12:            update = np.outer(err / Hinv[col, col], Hinv[col, col + 1:])            Wq[:, col + 1:] -= update    return Wq  if __name__ == "__main__":    np.random.seed(42)    rows, cols = 64, 256    W = np.random.randn(rows, cols) * 0.1    X = np.random.randn(cols, 64)     W_plain = plain_quantize(W, bits=4)    W_gptq = gptq_layer(W, X, bits=4)     err_plain = np.mean((W - W_plain) ** 2)    err_gptq = np.mean((W - W_gptq) ** 2)    print(f"朴素逐列量化 MSE: {err_plain:.6f}")    print(f"GPTQ 量化+误差补偿 MSE: {err_gptq:.6f}")    print(f"误差降低比例: {(1 - err_gptq / err_plain) * 100:.1f}%")
目的:用 numpy 模拟一层线性层的简化版 GPTQ 量化,对比朴素逐列量化与“量化+Hessian 逆误差补偿”在权重重建误差上的差距。
  1. H = 2 * (X @ X.T) + 1e-4 * np.eye(cols)用输入激活构造 Hessian 的近似,并加阻尼保证可逆,相当于画出该层的“承重地图”。
  2. err = dq - w量化前后该列的差值,即“被压缩袋挤压产生的形变量”。
  3. update = np.outer(err / Hinv[col, col], Hinv[col, col + 1:])把形变量按敏感度比例分摊到尚未量化的列上,这是误差补偿的核心一步。
  4. Wq[:, col + 1:] -= update真正执行“挪邻居”的操作,让剩余权重吸收量化误差。

常见误区

误区量化不就是把权重四舍五入到整数吗?精度损失是没办法的事,模型变笨只能认命。

正解GPTQ 的做法远不止取整。它先量化一列,再用 Hessian 逆矩阵把该列误差“分摊”到未量化列上。相当于压缩袋压扁一件衣服后,师傅会把旁边衣物的位置微调,让整个行李箱重新严丝合缝。误差确实存在,但被转移到了影响最小的位置。

为何常见:很多入门教程只讲对称/非对称量化映射,没提误差补偿机制,让人觉得量化就是“硬取整”。

误区分组量化既然能提升精度,那就把组设得越小越好,最好每个通道一组,这样最精确。

正解组越小,缩放因子和零点的数量越多,这些额外参数也要占用存储。加上每组独立统计 min/max 带来的冗余,压缩率反而会下降。GPTQ 在实践中常用 group_size=128 或 64,正是因为它在精度增益和参数开销之间找到了甜点。

为何常见:直觉上觉得“更细粒度更精确”,却没想到细粒度本身也有存储代价,就像分区太多之后,箱子壁占的体积比物品还大。

误区Hessian 矩阵是模型真实的二阶导数矩阵,用数学公式精确算出来的,所以补偿结果非常严谨。

正解实际操作中,Hessian 是用一批校准输入 $X$ 近似构造的($H \approx 2XX^{T}$),还要加阻尼项保证可逆。它是对权重敏感度的“经验估计”,而不是数学上严格的全模型二阶导。而且这个近似是逐层做的,不是全局的。

为何常见:看到公式就误以为是严格推导,没意识到工程实现中处处是近似和折中。

误区4 位整数只有 16 种取值,模型表达能力肯定大幅下降,对话质量必然断崖式下滑。

正解GPTQ 在多数语言任务上,INT4 的困惑度只比 FP16 高 1%~3%。配合分组量化和误差补偿,输出质量几乎无损。现在很多开源模型官方都提供 GPTQ INT4 权重,正是因为它在部署场景中已经足够可靠。

为何常见:早期量化方法只是简单截断,效果确实差,很多人用老经验推断新方法,忽略了 GPTQ 的补偿机制带来的质变。

面试题

Q1. GPTQ 引入 Hessian 矩阵的主要目的是什么?

单选题 · easy

  • A.感知权重敏感度指导补偿← 正确答案
  • B.提升训练收敛的速度
  • C.对模型输出做归一化
  • D.评估模型的推理延迟

答案:A。Hessian 矩阵相当于“承重地图”,对角元表示每个权重的敏感度,逆矩阵用来决定误差补偿的分配方向。B 是训练优化器的活,C 是归一化层的事,D 跟延迟无关。

Q2. GPTQ 属于哪一类量化方法?

单选题 · easy

  • A.训练时量化
  • B.训练后量化← 正确答案
  • C.蒸馏辅助量化
  • D.动态参数量化

答案:B。GPTQ 不需要在训练阶段介入,它用一小批校准数据在训练完成后对权重做逐层量化与补偿,属于典型的训练后量化(PTQ),与需要反向传播的量化感知训练不同。

Q3. 分组量化中 group_size=128 的含义是什么?

单选题 · mid

  • A.每128层共享一组缩放参数
  • B.每128个通道共享一组缩放因子← 正确答案
  • C.每128个样本更新一次参数
  • D.每128个批次做一次补偿

答案:B。group_size 指沿着通道方向每 128 个通道划为一组,组内共享同一个缩放因子和零点。它不涉及层、样本或批次的概念。

Q4. 以下哪些属于 GPTQ 的核心机制?

多选题 · mid

  • A.逐层最小化输出误差← 正确答案
  • B.用Hessian逆矩阵更新← 正确答案
  • C.给每层添加额外网络层
  • D.贪心策略选择权重列← 正确答案

答案:ABD。GPTQ 逐层处理,每层内部用 Hessian 逆做误差补偿,并用贪心准则决定先量化哪一列。它不修改网络结构,C 是错误项。

Q5. 朴素量化与 GPTQ 的关键区别是什么?

单选题 · mid

  • A.是否引入误差补偿机制← 正确答案
  • B.是否改变模型网络结构
  • C.是否增加更多训练数据
  • D.是否使用更大的训练批次

答案:A。朴素量化对各列独立取整,误差直接落在输出上;GPTQ 用 Hessian 逆把误差分摊到未量化列,相当于搬家时微调邻居家具来吸收形变,这是两者最本质的差异。

Q6. 在近似 H≈2XXᵀ 中,X 代表什么?

单选题 · hard

  • A.原始层的权重矩阵值
  • B.该层输入激活的样本矩阵← 正确答案
  • C.模型输出的标签矩阵值
  • D.量化误差的残差矩阵值

答案:B。H 由该层的输入激活 X 构造,X 是来自校准数据的一批样本矩阵。它刻画的是“对于这批输入,权重变化对输出影响多大”,而不是权重、标签或误差本身。

Q7. 关于误差补偿,正确的说法有哪些?

多选题 · hard

  • A.补偿作用在未量化权重上← 正确答案
  • B.补偿量由逆矩阵数值决定← 正确答案
  • C.所有未量化列均匀补偿
  • D.补偿方向与量化误差相关← 正确答案

答案:ABD。补偿只作用于还没被量化的列,幅度由 Hessian 逆决定,方向由逆矩阵和量化误差共同确定。它绝不是均匀分摊,而是按敏感度差异区别对待。

Q8. INT4 量化部署的主要收益是什么?

单选题 · easy

  • A.增加模型的参数量
  • B.扩大训练数据的规模
  • C.降低显存和推理成本← 正确答案
  • D.提升模型回答长度

答案:C。INT4 把每个参数从 16 位压到 4 位,显存占用降到四分之一,访存带宽压力减小,同等硬件下能服务更大的 batch,推理成本和延迟都显著下降。

Q9. GPTQ 的权重存储压缩比例约为多少倍?

单选题 · hard

  • A.2 倍
  • B.16 倍
  • C.4 倍← 正确答案
  • D.8 倍

答案:C。FP16 到 INT4 的位宽比是 16:4 = 4:1,所以权重存储和显存占用约压缩到原来的四分之一。要注意区分 4 倍压缩与 4 bit 位宽这两个概念。

Q10. 为什么需要分组量化而不是整层统一量化?

多选题 · extreme

  • A.各组分布差异大时精度更高← 正确答案
  • B.每组独立缩放适应异常值← 正确答案
  • C.组越小额外存储开销越低
  • D.组内缩放因子更贴合局部← 正确答案

答案:ABD。整层统一量化会被局部异常值带偏,分组后每组有独立的缩放因子和零点,能贴合局部分布、隔离异常值。但 C 说反了——组越小,缩放因子数量越多,额外存储开销越高。