X-Cache: Cross-Chunk Block Caching for Few-Step Autoregressive World Models Inference
🎯 一句话总结
X-Cache 发现了一个此前从未被利用的冗余维度——跨生成片段的 block 残差复用,在生产世界模型上以零训练代价实现了 2.6–2.7 倍加速,71% block 跳过率,画质无感知损失。
📌 核心问题:为什么世界模型推理太慢?
自动驾驶正越来越依赖世界模型——一种能根据车辆动作,实时生成逼真未来场景视频的 AI 系统。它相当于给汽车造了一个虚拟的沙盘世界,用来做强化学习训练和闭环评估。
但问题来了:这些模型推理太慢了!不够实时,就没法真正投入使用。
为什么旧方法不管用?
已有的扩散加速方法(如 DeepCache、FlowCache、SCOPE)都是利用同一个视频片段、相邻去噪步骤之间的特征冗余来跳过计算。但小鹏的世界模型已经被蒸馏成"少步模型"(仅 4 步去噪),每一步都在做实质性的结构更新,几乎没有可复用的冗余,强行复用只会破坏画质。
此外,交互式场景还有两个额外的拦路虎:
- 驾驶动作不连续:刹车、转向在每个片段边界可能突变,破坏了"特征平滑"假设
- 无法并行:必须先生成当前帧、等决策系统给出下一步动作,才能生成下一帧
💡 X-Cache 的顿悟时刻
研究者发现了一个新的冗余维度:真实世界的场景在相邻片段之间变化是缓慢而平滑的!
汽车从一帧到下一帧,路面、建筑、天空基本没变。因此,DiT(扩散变换器)中每个模块在"相同去噪步骤、相同模块编号"位置的输入,相邻片段之间高度相似。
这种"跨片段冗余"来自物理世界的连续性,而不是去噪过程,因此完全不受少步蒸馏影响——是个全新的可利用轴!
🔧 方法详解:X-Cache 是怎么工作的?
基础设定:三个下标刻画每次计算
模型用三个下标刻画每次计算:
- n:当前在生成第几个 chunk(视频片段)
- t:当前在第几步去噪
- b:当前在处理 DiT 的第几个 block
每个 block 做的事情是:新输出 = 旧输入 + block计算出的残差。X-Cache 的核心就是:把这个"残差"缓存下来,下次能用就直接复用,不用重算。
2.1 跨片段残差缓存(核心灵魂)
思路极其简洁:
- 当第 n 个片段的 (t, b) 位置计算完,把残差
r存入缓存 - 到第 n+1 个片段的同一位置,如果判断"输入和上一次差不多",就直接用缓存残差,跳过整个 block 的计算
第一个片段(n=0)是**“热身阶段”**,所有 block 都老老实实完整计算,把缓存填满,为后续复用打下基础。
2.2 双指标门控机制:聪明地决定"跳不跳"
不能无脑跳,得先判断当前输入和上一次是不是真的"差不多"。X-Cache 设计了一套**紧凑指纹(fingerprint)**来快速评估。
指纹怎么提取?
block 的输入是一个巨大的张量(帧数 × 高 × 宽 × 通道),全比太贵。于是按三维空间网格均匀采样 32 个 token,在帧、高、宽三个维度上按比例分配。
关键设计:不是沿着扁平 token 序列均匀采样,而是在三维空间里分别均匀采样!
为什么要这样?因为 1D 均匀采样对三个维度是"盲目的"——步长和维度大小的数值关系决定了采样会系统性地偏向某些坐标值。
一个灾难性例子:假设 F=2帧,H=4高,W=16宽,采样 K=8 个点。1D 均匀采样步长是 128÷8 = 16,恰好等于 W。结果所有采样点的 w 值全是 0——永远落在最左边一列,w=1 到 w=15 完全没被采样到!
正确的做法是按照三个维度的比例分别分配采样数量:
$$k_F : k_H : k_W \approx F : H : W, \quad k_F \cdot k_H \cdot k_W \approx K$$这样每个维度都有保证的覆盖,不会因为数字巧合而整体偏向某一侧。
两个辅助频道
指纹还拼接两个"辅助频道":
- 全局均值频道:整个输入的均值,用来捕捉整体漂移
- 动作条件频道:把当前驾驶动作向量(油门、转向等)也放进指纹,让系统能直接感知"这次动作和上次有没有变"——这很关键,因为动作是通过 adaLN-Zero 注入每个 block 的,光看输入张量察觉不到
两个指标联合判断
有了指纹,再用两个指标联合判断是否跳过:
| 指标 | 计算方式 | 捕捉什么变化 |
|---|---|---|
| 余弦相似度 | 取所有视角中的最小值 | 整体方向的漂移 |
| 最大 token 偏差 | 取所有视角的最大值 | 局部突变的异常点 |
只有当两个指标都通过,才允许跳过这个 block。这是一种"保守聚合"的安全设计。
📐 余弦相似度:为什么取最小值?
什么是余弦相似度?
余弦相似度的本质,是衡量两个向量方向有多一致,而不是它们有多"大"。
公式:
$$s = \frac{\vec{A} \cdot \vec{B}}{|\vec{A}| \cdot |\vec{B}|}$$分子是点积,分母是模长相乘——这个操作恰好等于两个向量夹角的余弦值。
- 方向完全相同 → 值为 1
- 方向垂直 → 值为 0
- 方向相反 → 值为 -1
为什么不用欧氏距离? 一个经典例子:
- A = [1, 2],B = [100, 200],C = [2, 1]
- A 和 B 的欧氏距离很远(差了 100 倍),但余弦相似度 = 1,因为方向完全相同
- A 和 C 的欧氏距离很近,但余弦相似度 < 1,因为方向有偏差
在神经网络的特征空间里,特征的"意义"更多藏在方向里,而不是幅度里。
为什么取最小值?
场景还原:X-Cache 的世界是 7 个摄像头,分成 3 个视角组,每个视角组独立计算一个余弦相似度值。
假设 7 个摄像头里,6 个的余弦相似度都是 0.999,但有 1 个(比如左后摄像头)突然出现了一辆加速超车的摩托车,相似度掉到了 0.80。
- 取平均:≈ 0.97,可能还是超过阈值,系统认为"没问题,跳过吧"——但实际上左后视角已经发生了显著变化
- 取最小值:直接拿到 0.80,远低于阈值,系统正确地判断"不能跳,必须重算"
本质逻辑:这个 block 的计算是针对所有摄像头一起做的,它们共享同一个 (t, b) 位置的计算。如果任何一个视角发生了显著变化,整个 block 的输出都会受影响——因为网络内部的注意力机制会跨摄像头交互信息。
生活类比:检查家里所有门窗是否都锁好了,判断标准不是"平均锁好程度",而是"有没有一扇是开的"——只要有一扇没锁,整体就不安全。
📊 最大 Token 偏差:捕捉局部突变
公式:
$$d_{\max} = \frac{\max\left|\phi(\mathbf{x}^{(n)}) - \phi(\mathbf{x}^{(n-1)})\right|}{\text{mean}\left|\phi(\mathbf{x}^{(n-1)})\right| + \epsilon}$$计算流程:
- 对 32 个采样位置,每个位置算当前片段和上一片段的特征差值
- 找出差值最大的那一个位置
- 用上一片段特征的均值做归一化,得到相对偏差
为什么要关注"最大"的那个位置?
一个典型场景:画面大部分区域(背景道路、天空)几乎没变,但某个局部位置(比如前方突然出现一辆急刹的卡车)发生了剧烈变化。
- 余弦相似度:因为大多数位置都很稳定,整体方向差异不大,可能不会触发报警
- 最大 token 偏差:那个"卡车突然出现"的位置偏差极大,直接把最大值拉高,触发强制重算
所以两个指标是互补的:
- 余弦相似度防的是"温水煮青蛙式的整体漂移"
- 最大 token 偏差防的是"局部突然爆炸式的异常变化"
2.3 自适应阈值:会自我调节的"松紧度"
固定一个全局阈值太粗暴——有些 block 天生就变化小(可以激进地跳),有些天生变化大(要保守)。
X-Cache 为每个 (t, b) 位置单独维护一个指数移动平均(EMA),记录这个位置历史上的余弦相似度,然后把阈值设为略低于 EMA 的值(差一个边距 m=0.02)。
效果是:
- 跨片段几乎不变的模块 → 阈值越来越高,越来越激进地跳
- 变化较大的模块 → 阈值会自动保守
同时设定一个硬性安全底线(τ_floor=0.97),不管 EMA 多高,阈值都不会低于这个值。
2.4 四重安全机制:强制重算的边界条件
即使指纹通过了测试,也有几种特殊情况必须"强制重算":
① 去噪步骤 t=0 保护(可选)
第 0 步的输入充满高斯噪声,条件信号(动作、文本等)对输出的影响最大,而且每次更新 KV 缓存时噪声都会重采样,导致相邻片段的 t=0 余弦相似度天然偏低。默认关闭跳过,确保条件信号能被充分吸收。
消融实验表明:开启保护后跳过率从 71.3% 降到 53.5%,但画质毫无变化。自适应阈值已经能自己判断好 t=0 的情况。但研究者保留了这个开关,作为夜间、暴雨或极端轨迹变化下的额外安全边际。
② 锚块(Anchor Blocks)保护
默认让第 0 个 block(前锚)永远不跳过。它的输出变化会像多米诺骨牌一样级联到后续 block,天然地迫使后续 block 重新计算它们自己的指纹——这是个优雅的级联保护机制。
③ KV 更新帧保护(最重要!)
自回归生成时,每隔一段时间会有一个"KV 更新帧",把当前生成的干净帧写入持久 KV 缓存,供未来所有片段的 cross-attention 使用。
如果这次写入的 KV 带有缓存误差,未来所有帧都会受到污染,错误会永久传播!
消融实验证明:关掉 KV 更新帧保护,PSNR 从 53.4 dB 崩塌到 21.5 dB,LPIPS 暴涨 3 个数量级——图像完全崩了!这是唯一不可妥协的硬性安全要求。
④ 最大过期次数
如果某个 (t, b) 位置连续跳过次数超过阈值 M,强制重算一次,防止缓存太陈旧。
🧪 实验结果:在真实赛道上跑一跑
实验设置
| 项目 | 详情 |
|---|---|
| 硬件 | 阿里 T-Head 真武(Zhenwu)810E AI 加速器,96GB HBM2e,BF16 精度 |
| 模型 | 小鹏自研 X-World(基于 WAN 2.2),7 个摄像头,12 帧/秒,4 步去噪 |
| 数据集 | 城市道路(7条)、高速公路(3条)、城市掉头(3条) |
| 视频长度 | 每条 264 帧(约 22 秒) |
核心结果
| 场景 | PSNR | SSIM | LPIPS | 跳过率 | 加速比 |
|---|---|---|---|---|---|
| 城市道路 | 51.37 dB | 0.9990 | 3.3e-4 | 71.4% | 2.65× |
| 高速 | 54.67 dB | 0.9991 | 1.9e-4 | 71.6% | 2.66× |
| 掉头 | 52.04 dB | 0.9990 | 3.1e-4 | 71.3% | 2.70× |
加速效果稳如磐石:三种场景的跳过率只差 0.3 个百分点,推理时间只差 30ms——加速是由 DiT 的结构(block 位置)决定的,不是场景决定的。
掉头反而比城市道路画质更好? 看似反直觉,但有合理解释:掉头片段中大部分时间其实在直行;转弯时摄像头里物体本来就有运动模糊,高频纹理本来就少,缓存误差更难在像素上显现。
误差分布分析
所有场景下:
- Blocks 1-19 的跨片段余弦相似度都在 0.95 以上
- Blocks 20-26 降到约 0.90(这个模式完全由模型结构决定,与场景无关)
跳过率对应地:
- Blocks 1-19 稳定在约 0.75(1 个热身 chunk 对应的 4 个 chunk 复用窗口)
- Blocks 20-26 降到约 0.69
🔬 消融实验:拆开零件逐个测
| 实验 | 效果 |
|---|---|
| t=0 保护开启 | 跳过率 71.3% → 53.5%,加速 2.59× → 1.84×,画质不变(自适应阈值已能自行判断) |
| KV 更新帧保护关闭 | PSNR 53.4 dB → 21.5 dB(崩塌!),LPIPS 暴涨 3 个数量级 |
| 前锚块 Fn=0(关闭) | 跳过率多 1.9%,每 chunk 省 70ms,画质几乎不变(但保留为安全边际) |
| τ_floor 从 0.90 → 0.96 | 所有指标完全不变(当前数据集中几乎没有 token 落在这个区间) |
❓ 技术细节问答
Q1:余弦相似度中位数和 75 分位数都是 1.0,这合理吗?
完全合理!
物理世界连续性决定了:车辆以正常速度行驶时,相邻两个 chunk 之间可能只过了零点几秒:
- 远处的建筑、天空、道路线几乎纹丝不动
- 前方车辆可能只移动了几厘米
- 大量摄像头画面的大部分区域像素级别上都几乎一样
神经网络的特征是从像素里提取的——如果输入像素都没怎么变,特征自然也不会变。
测试集的高速公路和城市直行占了绝大多数时间,“场景几乎静止"的 chunk 占了绝大多数,对应的余弦相似度自然集中在 1.0。
这个现象反过来印证了 X-Cache 的核心前提:驾驶世界模型的跨 chunk 冗余极高,不是"大概差不多”,而是"大多数情况下特征根本就没变"。
Q2:Chunk 是什么?
Chunk 就是世界模型每次生成的一小段视频片段。
世界模型不是一口气把整段视频全生成出来的,而是像说话一样一段一段往外"吐":
chunk 1 → chunk 2 → chunk 3 → chunk 4 → ...
每个 chunk 包含若干帧画面,生成完后交给决策模块,决策模块根据画面决定下一步动作(转向、油门),再把动作传回来,生成下一个 chunk。
这就是闭环交互:
生成 chunk n → 决策系统观察 → 发出动作 → 生成 chunk n+1 → ...
每个 chunk 内部还有去噪过程:
噪声 →[t=0]→[t=1]→[t=2]→[t=3]→ 清晰画面
所以论文里有两个嵌套的循环:
- 外层:chunk n → chunk n+1 → …(自回归生成)← X-Cache 利用这个轴的冗余
- 内层:去噪步骤 t=0 → t=1 → t=2 → t=3(扩散去噪)← 旧方法盯着这个轴,但 4 步去噪里几乎没有冗余
🚧 局限性:诚实的声明
论文非常诚实地列出了边界条件:
- 所有测试只在 22 秒以内的片段、X-World 训练分布内的场景上做过——夜间、暴雨、激进驾驶、长时间高速巡航等场景尚未验证
- 超参数是针对单个 held-out 片段调的,选择的是"安全而非激进"的配置,当前 PSNR 约 53 dB、SSIM>0.999 实际上有相当余量
- Pareto 前沿尚未探索,降低 τ_floor、放松 τ_dev、减少前锚等操作可以换取更高跳过率
📝 结论与思考
X-Cache 的创新点在于找到了一个与现有方法正交、互补的冗余维度:
- 现有方法:跨去噪步骤缓存(适用于多步扩散)
- X-Cache:跨生成片段缓存(适用于少步蒸馏后的模型)
两个轴可以叠加使用,而不是竞争关系。
关键启示:
- 工程优化要从数据本身的特性出发——物理世界连续性是真正可靠的冗余来源
- 安全机制要分层设计——KV 更新帧保护是硬性要求,其他是软性安全边际
- 自适应机制让系统在不同场景下自动调节行为,减少人工调参负担
这是一篇来自工业界、非常接地气的系统优化工作:发现了一个被学术界忽略的新冗余维度,用一套精心设计的安全机制把它安全地用起来,在真实生产系统上拿到了 2.6 倍的加速。