大模型推理的 KV 缓存,过去只需要伺候一种注意力机制。FULL 注意力、滑动窗口注意力、MAMBA 状态空间模型,但凡只跑其中一种,缓存怎么设计都大差不差。但现在的趋势是把它们搅在一起,一个模型里同时跑 FULL、SWA 和 MAMBA 组件,缓存的复杂度立刻翻了倍。每引入一种新的注意力,就得单独写一套缓存逻辑,不同逻辑之间还要拼命对齐复用规则,工程团队被这种缝合怪折腾得够呛。LMSYS 那帮搞 Chatbot Arena 的人看不下去,直接推翻了老方案,提出 Unified Radix Cache——用一颗以 token 为键的基数树,把三种组件的缓存全部统一起来,SWE-bench 实测首 token 延迟最高砍掉 16.6%。这不是简单的代码重构,而是从拓扑结构上重新定义了混合模型的缓存该如何运转。
混合模型把 KV 缓存变成了缝补现场
一份缓存不够用,三份又太蠢
传统的 KV 缓存是为一对一场景设计的。FULL 注意力需要完整的序列缓存,所有历史 token 的键值对都得保留;滑动窗口注意力只保留最近 W 个 token 的缓存,窗口外面的东西直接丢掉;MAMBA 状态完全是另一套玩法,它依赖的是固定大小的状态向量,没有传统意义上的键值对,但同样需要缓存来避免重复计算。这三种缓存若各自独立实现,逻辑倒是简单,问题是系统要维护三套完全不同的存储、三套不同的检索路径以及三套不同的失效机制。推理框架的资源开销和工程复杂度随之暴涨,而且随着混合模型越来越火,这个三角债只会越欠越多。
手工对齐的复用规则经不起推敲
更让人头疼的是缓存复用。生成式推理中,前缀共享是压延迟的关键手段——前一条请求的缓存应该能被后续请求复用。但在混合模型里,FULL 组件的复用规则基于完整序列匹配,滑动窗口组件依赖窗口内 token 的子序列匹配,MAMBA 组件则要求状态参数完全一致才能复用。工程上大家通常手工写一堆条件判断,把三种组件的复用规则强行拧在一起。这种手缝方案脆弱得可怕,随便加一种新的混合配置,复用逻辑就得重写一遍。而且一旦某个组件的缓存没对齐,错的不是一点点,而是整条请求都可能崩掉。这种缝补模式,实在不配被称为缓存系统。
Unified Radix Cache 的解法:树与钩子
一棵基数树,收束三种注意力语义
LMSYS 团队的核心思路是把缓存结构从“按注意力类型分库”切换到“按 token 序列建树”。Unified Radix Cache 内部是一棵统一的基数树,每个节点以 token 作为键,整棵树记录的是完整的序列拓扑。对于 FULL 注意力,自然走完整路径;滑动窗口注意力无需单独维护窗口缓存,它在同一棵树上按窗口长度走一段截断路径即可;MAMBA 组件同样不另起炉灶,而是从这棵树的路径上提取状态快照作为检查点。这意味着混合模型中所有组件的缓存都共享同一片 radix 拓扑,三种语义被统一编码进同一套结构里,而非用三套结构去模拟一套逻辑。这种拓扑层面的收束,让缓存一致性第一次得到了结构性的保证,而不是依赖人力去维护对齐。
组件钩子把“怎么跑”和“怎么存”彻底解耦
统一拓扑只是第一步。不同注意力组件的执行路径差异仍然存在——FULL 需要完整上下文,滑动窗口无视远期 token,MAMBA 有自己独立的状态转移逻辑。Unified Radix Cache 引入了一个关键的抽象:组件钩子。每个组件向基数树注册自己的执行路径、窗口设定和检查点复用语义,树本身只负责维护拓扑和提供检索接口,不管组件内部怎么计算。换句话说,“缓存该怎么复用”由基数树统一调度,“各个组件怎么跑”由钩子各自定义。这套机制彻底告别了手写条件判断,也让混合模型可以像搭积木一样组合不同注意力部件,而不用每次都为缓存重新写胶水代码。
16.6% 的 TTFT 下降,靠的不是魔法
SWE-bench 上的延迟压测账本
Unified Radix Cache 拿 SWE-bench 做测试靶场,这个基准测的是代码生成场景,前缀共享极度密集,对缓存复用效率极其敏感。实测结果显示,相比传统多缓存方案,采用统一基数树后 首 token 延迟最高下降 16.6%。这背后没有引入新的计算加速,纯粹是因为缓存命中率被拉高了。原来三种缓存各管各的,很多本可复用的前缀因为组件边界对不上而被放弃;现在整棵树一张图,一个前缀只要 token 序列一致,任何组件都能直接复用对应路径上的缓存结果。少算的每一点键值矩阵乘法,都直接变成了延迟上的数字下降。
独立执行路径与检查点复用如何联手省力
延迟下降的另一块功劳属于滑动窗口和检查点复用的协同。滑动窗口组件在同一棵基数树上按窗口长度自然截断路径,窗口外的 token 虽然不参与本次计算,但路径上的缓存条目依然存在,后续请求如果用到那些远期 token,根本就不需要重新计算,直接命中缓存。MAMBA 组件的检查点复用更是精妙,状态快照被打在基数树的节点上,不同请求只要经过同一个前缀节点,状态就可以直接捡起来用,省去了重跑整个状态空间模型的代价。独立执行路径保证了每个组件的计算语义不被破坏,而统一的树结构让这些语义之间可以无感知共享缓存,整个系统的无效计算被压到极低。
统一缓存之后,部署还能再轻一点
GPU 显存里的隐性浪费被堵上了
KV 缓存是 GPU 显存里的大户。混合模型如果维持多套独立缓存,不仅浪费存储空间,还会因为碎片化导致显存利用不充分,进一步拖慢 batch 效率。Unified Radix Cache 将三套缓存压缩为一套 radix 拓扑,逻辑上消灭了重复存储的可能——同一个 token 序列不管被多少种组件用到,基数树里只留一份。这个瘦身效应在高并发、长序列的部署场景下尤其明显,原本被冗余缓存占用的显存可以被释放给更大的 batch size 或者更长的上下文窗口,对吞吐的增益是连锁反应式的。
混合架构的部署门槛被结构性地降低
统一基树的价值不止在当下的性能提升。模型未来只会更加混合,FULL+SWA+MAMBA 只是开始,之后可能再加入线性注意力、稀疏注意力甚至别的什么新组件。如果每次都得为缓存重新造轮子,框架将永远跟不上模型演化的节奏。Unified Radix Cache 把缓存和具体的注意力实现解耦,让部署框架终于有了一个标准化的缓存接口——只要新组件按照钩子规范注册自己的执行路径和复用语义,就能融入基数树,享受同样的命中率和一致性保障。这种结构化抽象,是推理系统真正走向工业化的标志。

