STEPQuant:取代 KV cache 的状态,6-bit 量化精度不掉

一、为省内存而生的结构,怎么自己成了显存大头?

推理系统的显存账本上,有一种结构存在的全部理由就是省内存。softmax attention 要为每个历史 token 缓存一份 key 和 value,序列越长这笔账越大,这就是 KV cache。线性注意力换了一条路:它不再逐 token 记账,而是把整段历史压进一个尺寸固定的循环状态,状态大小与序列长度无关。

听上去这像是把显存焦虑一次性解决了。可 STEPQuant 这篇论文的开篇图,给出的画面恰好相反。

循环状态为什么需要结构化压缩

图注:论文 Figure 1 的三块面板。(a) 中 Qwen 的显存随并发请求数增长,FP32 精度的循环状态池在约 70 路并发时越过 BF16 权重占用,而 6-bit 的 STEPQuant 曲线远在其下。(b) 是 2304 个 Qwen head 上,INT6 量化累积误差与 gate 半衰期的散点,整体呈上升趋势。(c) 是 Qwen(实线)与 KDA(虚线)在七个任务上的平均准确率柱状图,统一 INT6 与 INT4 明显塌陷,STEPQuant@6bit 几乎与 FP32 重合。STEPQuant

图左侧藏着这个反差的第一层原因。当约 70 路请求同时在线时,FP32 精度的循环状态池占用的显存就超过了整个模型的 BF16 权重。一个为省内存而设计的结构,在高并发服务里反而成了显存大头。道理不难想:权重全局只有一份,循环状态却要为每个并发请求各驻留一份,请求越多,这笔开销越不可忽略。

图右侧给出第二记闷棍。最顺手的省内存手段是把状态压到低比特,这也正是 KV cache 量化的常规做法。可在这套状态上,统一比特的量化会直接崩掉。Qwen 七个长生成任务的平均准确率从 FP32 的 80.60 跌到 INT8 的 71.86,INT6 只剩 45.04,INT4 干脆掉到 12.73。Kimi 上趋势一样,从 61.52 一路滑到 21.63。

更值得注意的是崩溃的形态。它不是随比特数平滑地缓慢退化,而是在一个看似安全的档位上就出现断崖:INT8 已经把 Qwen 拉低近 9 个点,INT6 只剩一半,到 INT4 几乎等于报废。这和 KV cache 量化的经验很不一样,缓存即便压到 4-bit 甚至更低,通常还能画出一条可用的退化曲线;而循环状态的低比特是一条陡峭的悬崖。

同一套低比特手段,在 KV cache 上屡试不爽,搬到循环状态上为什么会彻底失效?答案不在量化器本身,而在这个状态是怎么被写出来的。

二、一个会被反复改写的状态:误差为什么留得下来?

先看两种记忆的区别。KV cache 像一份只增不改的会议录音转写稿:每个 token 对应独立的一行,把某一行量化得粗糙一点,误差就留在那一行,不会污染别处。循环状态则像一份被反复改写的会议纪要:每读进一个新 token,整份纪要都会被门控衰减一遍,再被最新的 key/value 覆盖一部分。早期写错的一个数字,会被后面的每一版纪要继承下去。

这个"改写"在数学上就是 gated delta 规则。用 $S_t$ 记第 $t$ 步的循环状态(一个 $d_k \times d_v$ 的矩阵),更新式为

$$S_t = (I - \beta_t k_t k_t^{\top}) D_t S_{t-1} + \beta_t k_t v_t^{\top}$$

其中 $k_t$、$v_t$ 是当前 token 的 key 和 value 投影,$\beta_t$ 控制这次写入的强度。$D_t$ 是遗忘门,Gated DeltaNet 里它是一个 head 共享的标量 $\alpha_t$,而 Kimi Delta Attention 把广播到每个 head 的标量升级成了逐通道的对角矩阵,让不同的特征维度有各自的遗忘速度。Gated DeltaNet Kimi Linear

STEPQuant 评估的 Kimi-Linear-48B-A3B-Instruct 就是这种设计的产物:它把每三个 KDA 层与一个全注意力 MLA 层交替堆叠,总共 48B 参数、每次前向只激活约 3B。这一点很关键,因为量化要处理的不是一摞同质的注意力层,而是"固定大小的 KDA 循环状态"与"少量仍随序列增长的 MLA 缓存"并存的混合结构。Kimi Linear

Gated DeltaNet 的模型结构与 block 设计

图注:论文 Figure 1,Gated DeltaNet 的宏观结构(左侧与中间两条 hybrid stack)与单个 token-mixer 的 block 设计(右侧)。右侧灰色方框里,q/k/v 三条投影路径与 α/β 两条门控投影汇聚到中间的 gated delta-rule kernel,正是上面那条更新式在工程里的样子。Gated DeltaNet

误差为什么留得下来,可以从这条更新式直接推。设量化后的状态与真实状态之差为 $E_t$,代入更新式展开,会得到一个干净的递推关系:$E_t = A_t E_{t-1} + \varepsilon_t$。等式右边第一项是上一步误差被过渡矩阵 $A_t$ 搬运过来的部分,第二项 $\varepsilon_t$ 是这一步量化新引入的噪声。关键在过渡矩阵的性质:在 $|k_t|_2 \le 1$、$0 \le \beta_t \le 1$、$0 \preceq D_t \preceq I$ 的条件下,可以证明 $|A_t|_2 \le |D_t|_2 \le 1$,也就是说误差不会被无限放大,但也不会自动消失。这条递推式是整篇论文的支点,它把"量化误差会不会累积"变成了一个关于过渡矩阵 $A_t$ 的问题:$A_t$ 会把多少旧误差留下来,直接决定了这一单元的比特有多值钱。

更细一点看:delta 因子 $(I - \beta_t k_t k_t^{\top})$ 只压制沿当前 key 方向的误差分量,与 $k_t$ 正交的那些分量压不掉,只能靠遗忘门 $D_t$ 慢慢衰减。遗忘门越接近 1,误差衰减得越慢,于是活得越久的记忆单元,攒下的误差就越多。到这一步,"给误差算寿命"的动机已经浮出水面。换个说法,gated delta 规则把两种记忆机制叠在了一起:遗忘门按固定节奏整体衰减,delta 更新精确覆盖某一条 key 对应的旧关联。前者像定期清空,后者像定点涂改,两者互补,也让误差的传播同时受这两条路径支配。

三、误差的价值并不均匀:它在时间上活多久,在空间上伤哪一行?

一个直接可检验的问题是,寿命长的单元是不是真的攒了更多误差。论文在 2304 个 Qwen head 上做了统计,把 INT6 量化后的累积误差和 gate 半衰期放在一起看,两者呈现明显的正相关,Spearman 相关系数约为 0.80。这不是感觉,是一个可以在校准数据上量出来的经验规律。沿着这条规律,论文给每个单元定义了一个寿命权重 $L_u = \sum_j \exp(2j\ell_u)$,其中 $\ell_u$ 是该单元平均的对数保持率。这个几何级数把"活多久"翻译成了一个可以直接参与运算的数值。$L_u$ 越大,这个单元越"记仇":它会在很多步之后仍把当初的量化噪声带进输出。于是"给误差算寿命"这句话不再是一个比喻,而是一个能在校准数据上估出来、并写进优化目标的量。STEPQuant

时间维度说完了,空间维度是另一半。循环状态是一个矩阵,它的不同 key 行对最终输出的影响并不一样。论文从读出误差入手定义了每一行的影响分数 $\omega_i$,衡量的是一行状态扰动会在多大程度上改变当前步的输出。然后做了一个很直观的实验:把 key 行按影响大小排序,分成八组,逐组量化到 INT4,看困惑度涨多少。结果符合直觉,影响越大的组,被压到 INT4 后困惑度涨得越凶。

这里的影响分数不是拍脑袋的代理量,它从读出误差反推而来。当前步的输出等于状态矩阵与 query 相乘,某一行状态的扰动会按 query 在该方向上的分量被送进输出;把这一步的系数取平方、再在校准集上取期望,就得到这一行的 $\omega_i$。换句话说,它衡量的正是"这一行错了,输出会被带偏多少"。

循环状态在行与列两个方向上的异常值结构

图注:论文 Figure 2。(a) 是把 key 行按读出影响排序、分成八组后逐组量化到 INT4 的困惑度增量,高影响组涨幅更大。(b) 是一个代表性 Qwen 状态的 128×128 热力图,明亮的异常值同时出现在 key 行方向和 value 列方向。(c) 是 2048 个解码步上相对中位数的通道 RMS,少数通道始终维持在十几倍量级。STEPQuant

热力图暴露出一个更容易被忽略的事实:异常值不只在行方向有,列方向同样存在,而且量级都不小,行的最大到中位比约为 10.3 倍,列约为 19.4 倍;论文还报告 98.6% 的采样状态在两个方向上都超过 3 倍。这意味着任何只用一条轴的缩放方案,必然漏掉另一个方向的分布。更麻烦的是,图(c)显示这些异常值在整个解码过程中持续存在,不会随步数淡去。

另一支同期工作 DAMP 独立地观察到了同一类现象,它发现决定误差持久性的是通道级的衰减,而且通道按衰减排序的结果在不同任务间高度稳定。DAMP 两个团队从不同角度走到同一个结论,说明"误差的时空不均匀"不是某一次实验的偶然。到这里,比特该怎么分的问题已经可以被精确地提出来:把同一枚比特放在寿命长、又更多把误差送进输出的那些行上,它比放在别处值钱得多。

四、把误差的时空价值翻译成比特预算

STEPQuant 把上面两个观察落成了两半方法,一半管时间、一半管空间。

时间那一半是一个带预算约束的分配问题。目标是最小化按寿命权重加权的总误差,约束是所有单元分到的比特数之和不超过总预算。翻译成人话:谁的寿命权重高,谁就多分比特。但这里有个转折,少数风险最高的单元其实很难靠"多分一两比特"救回来,论文干脆把它们整体留在 FP16,当作稀疏的支点(pivot)。在 Qwen 上,这类单元只占约 1.39% 的 head,但消融实验显示,这少数支点极其关键:4-bit 配置下,带上它们比去掉它们在三任务平均上高出 6.70 个百分点。小数目的高精度保留,换来了整个低比特方案的可信度。分配所需的统计量全部来自离线段的一小段校准数据,论文用的是 32 段、每段 2048 token 的 WikiText-2 训练文本;校准只跑一次,之后每一步解码都不再有分配开销。

空间那一半是一次几何拟合。既然行和列两个方向都有异常值,就同时拟合一个行因子和一个列因子,让状态元素写成 $\hat{X}{ij} = r_i c_j z{ij}$,$r_i$ 管行、$c_j$ 管列、$z_{ij}$ 是被量化到低比特的残差。列因子在一个加权平方误差下最小化,权重 $w_i$ 来自前面那个读出影响分数。行因子取 $r_i = m_i^{1/2} w_i^{-1/2}$,同时吃进这一行的幅值 $m_i$ 和它对输出的影响 $w_i$。行因子与列因子相乘,等于给每个元素在两个方向上各配一个独立的缩放,行方向压掉大幅值,列方向对齐分布,而拟合时读出影响大的行会被赋予更高权重。它和 SmoothQuant 式单轴缩放的区别,不在于技巧,而在于权重从哪来:单轴方案看的是单纯幅值,STEPQuant 看的是这一行会怎样改变输出误差。PTQ Survey

两条轴分别拟合的量化思路并非全新。Q-Mamba 早就在 Mamba 状态上做过 channel/state 双轴尺度,只是它的两轴来自状态方差结构,还没绑到读出误差上;Q-Mamba 更早的 Quamba2 则在 Mamba 上走通了从权重到激活的整条低比特链路。Quamba2 STEPQuant 的新增之处,是把双轴绑到了错误驱动的行影响权重上。

这两半方法也不是各自独立地加分。Qwen 上的一组消融给出了很清楚的分工:只用空间一侧,平均分是 73.95;只用时间一侧,更是掉到 12.87;而时间和空间合在一起的完整版本达到 84.72,与 FP32 的 84.61 基本持平。作为对照,直接搬用 Q-Mamba 的双轴方案在 4-bit 下只有 7.64。两个维度缺一不可,这一点从数字上被钉死了。

落到工程上,这套方法被切成离线、在线两段。离线段用校准数据估计寿命权重和行影响,在预算约束下分配比特、挑出支点,并拟合出行列因子。在线段,一个融合 kernel 把解压、delta 更新、当前步读出合成一步,不把完整状态单独物化;head 输出交给下游后,另一条 CUDA stream 再把压缩后的状态写回,让缩放更新与模型计算重叠。

五、6-bit 真的追平 FP32 了吗?4-bit 的隐形代价藏在哪?

数字摆出来最直接。在 Qwen3.8-27B 和 Kimi-Linear-48B-A3B-Instruct 两个 GDN/KDA 混合模型上,七个长生成任务的表现为:

配置Qwen 7 任务平均Kimi 7 任务平均
FP32 状态80.6061.52
uniform INT871.8656.02
uniform INT645.0445.70
uniform INT412.7321.63
STEPQuant@6bit80.5961.47
STEPQuant@4bit80.5158.52

6-bit 的 STEPQuant 与 FP32 的差距小到可以忽略,Qwen 上只差 0.01 个点。真正反直觉的是 4-bit:80.51 不仅远高于统一 INT4 的 12.73,还反超了统一 INT8 的 71.86。这说明 4-bit 之所以能赢,靠的不是更聪明的量化器,而是前两章那套时空分配,把有限的比特放到了真正值钱的位置。STEPQuant

统一 INT8 用了 8 位、却比 6 位甚至 4 位的 STEPQuant 还差,这个对比说明关键从来不是"用了几位",而是"这些位放在了哪里"。

平均分之外还有两层检查。一是短生成任务:4-bit 的 STEPQuant 在 MMLU、ARC-C 这类任务上平均只落后 FP32 约 0.15 个点(Qwen)和 0.25 个点(Kimi),说明它的优势不是靠长输出刷出来的。二是权重也被量化的情况:当权重本身已经用 AWQ 压到 INT4,6-bit 的 STEPQuant 仍能拿到 Qwen 79.27、Kimi 58.62,与 FP32 状态的差距只有 0.05 和 0.33 个点。低比特权重叠加低比特状态,这个组合并没有让精度雪崩。

但只读平均分会被骗。有一个不进平均分的副作用,藏在校准指标之外:生成长度。模型在被压到过低比特后,会变得"想个没完",输出很长却答不对。Kimi 在统一 4-bit 下,AIME 上的平均输出长度被推到约 63.40K token,HMMT 上约 64.22K token,都逼近 65536 的采样上限,而准确率几乎为零。STEPQuant@4bit 的生成长度则贴近 FP32。Qwen 的 STEPQuant@4bit 也会出现输出变长的迹象,不过它的平均分仍接近 FP32(80.51 对 80.60)。

STEPQuant 的生成长度与在线服务效率

图注:论文 Figure 3。(a–b) 是 Qwen 与 Kimi 在 FP32、统一 INT8/6/4 以及 STEPQuant@6bit/@4bit 下、按任务等权平均的生成长度柱状图,统一 INT4 的柱子明显最高,部分任务接近上限。(c) 是带 W4 权重的 Qwen 总服务显存随 batch 的变化。(d) 是 batch 512 下状态内存与更新时间的归一化结果。STEPQuant

同一时期还有另一条路线值得一提。DAMP 也走衰减感知的混合精度,但它选择更保守也更简单的设计:每个 head 固定把风险最高的 16 个 key channel 留在 FP16,其余用 INT8 加缩放与重排,平均每个状态值约 9.9 比特,换来 69.1% 的状态存储下降和 2.59 倍的状态更新加速。用更高的比特预算买更简单的设计,和 STEPQuant 用 6-bit、4-bit 换更强的分配能力,是两种不同的取舍。DAMP

所以,读到"4-bit 接近 FP32"时,至少要同时看两件事:平均分有没有守住,以及模型是不是靠更长的输出把答案蒙出来的。

六、从实验数字到线上部署:5× 压缩、68.7% 显存,这个结论能走多远?

把方法接进真实服务系统,才是这篇论文最有分量的一块。论文在 SGLang 上做了端到端测量,用的是 AWQ-INT4 权重、batch 512 的设置:

指标结果
Qwen W4 总服务显存(batch 512)419.73 → 131.18 GiB(−68.7%)
循环状态内存下降 80.1%(5.03× 压缩)
状态更新时间下降 65.6%(2.91× 加速)
Kimi 状态压缩 / 总显存5.08× / 下降 53.7%

这些数字要连着条件读。它们是四张 A800(张量并行 TP4)、特定 batch 与负载下的测量,其中总显存那一行包含权重,不能等同于纯状态显存。而所谓 5.03×、6.93× 的压缩比,是包含 FP16 支点在内的标称平均值,并不是说每个状态元素都被严格压到统一的比特数。

为什么落地要选 SGLang?因为循环状态池不能只是一个孤立的算子,它必须嵌进请求级的内存生命周期里。SGLang 的 RadixAttention 用一棵基数树管理跨请求可复用的 KV cache,配合叶优先的 LRU 淘汰和引用计数。新增的状态池要在这个框架里被分配、复用和回收,才谈得上服务收益。

SGLang 的 RadixAttention 跨请求缓存管理

图注:SGLang 论文 Figure 3,RadixAttention 在九个时间点上的基数树演化。节点以绿色、蓝色、红色区分新增、被访问与被淘汰,树边标注 token 子串,示例覆盖两段 chat、few-shot 查询与 self-consistency 采样,展示前缀匹配、节点分裂与 LRU 淘汰。SGLang

需要说清的是,2023 年的 SGLang 论文本身并不包含 GDN/KDA 状态量化,packed-state kernel 是 STEPQuant 叠加在它之上的部分;SGLang 在这里承担的是"可信的 serving 载体",而不是量化方法本身。这也解释了为什么论文要把方法落在 state pool 上:状态量化的收益只有和请求调度、内存回收、连续批处理一起算,才会兑现成端到端的显存与延迟改善。

那么,这篇论文的结论能走多远?论文自己列出的局限很诚实。第一,寿命权重 $L_u$ 只是通过门控衰减来近似误差的持久性,没有完整建模随时间和 key 变化的动态转移,因此对长期影响只是近似。第二,在 BF16 权重加 4-bit 状态的组合下,KDA 在长生成任务上会掉点,Qwen 则会出现生成长度变长的现象。第三,评估只覆盖两个 GDN/KDA 混合模型和 A800 一种硬件,换架构、换硬件、换动态负载都还没验证。此外,模型名 Qwen3.8-27B 的独立确认、以及论文自称的 ICLR 2027 录用状态,都还属于待核实项。DAMP 那边同样承认,即便用上保护通道,INT4 和 NVFP4 也还恢复不了 FP32,这不是 STEPQuant 一家的短板。

值得注意的是,这并不是孤立的一次尝试。Quamba2 和 Q-Mamba 在 Mamba 系列上、DAMP 在同期,都从不同角度逼近同一个结论:循环类状态的低比特量化,必须按误差的结构来分配精度。STEPQuant 的价值在于把"结构"拆成了时间和空间两个可量化的坐标,并让这两个坐标直接进入比特预算。

一句话收束:这篇论文最可信的是"误差的时空价值不均匀、按此分配比特确实有效"这条机制,以及支撑它的对照实验;需要打问号的是跨模型、跨硬件的部署外推,和 4-bit 状态本身的长期稳定性。它给出的不只是一个 6-bit 的配置,而是一把尺子:在任何一个会把误差一代代续写下去的循环记忆里,都该先问一句,这枚比特到底该放在哪。

想深入可以读原文:STEPQuant: When and Where Errors Matter in Delta-Rule Recurrent State Quantization — arXiv:2609.38169

参考文献

  • STEPQuant: When and Where Errors Matter in Delta-Rule Recurrent State Quantization — arXiv:2609.38169
  • Gated DeltaNet: Improving Mamba2 with Delta Rule — arXiv:2412.06464
  • Kimi Linear: An Expressive, Efficient Attention Architecture — arXiv:2510.26692
  • DAMP: Decay-Aware Mixed-Precision Recurrent-State Quantization — arXiv:2608.27513
  • Q-Mamba: Towards more efficient Mamba models via post-training quantization — ACL Findings 2025
  • SGLang: Efficient Execution of Structured Language Model Programs — arXiv:2312.07104
  • A Survey of Quantization in LLM: Unlocking Potential Hardware Efficiency — JCST 2026
  • Quamba2: A Robust and Scalable Post-Training Quantization Framework for Selective State Space Models — arXiv:2503.22879
STEPQuant:取代 KV cache 的状态,6-bit 量化精度不掉