技术博客

滑动窗口与 RoPE 的交互:窗口内一致性的得与失

第 88 / 147 篇 · 2026-03-02 · ai · 滑动窗口注意力位置编码推理部署

滑动窗口注意力(SWA,第 4120 篇)和 RoPE(第 5010 篇)各自都简单,组合起来却有几处容易踩的交互。这篇按"一致性从哪来、坑在哪"讲。

相对位置一致性:RoPE 最喜欢的窗口

SWA 规定位置 $i$ 只能看见 $[i-w,\,i]$。配合 RoPE,打分里的位置项只依赖相对距离 $r = i - j \in [0, w)$——一个有界区间。这意味着:只要推理时的窗口尺寸 $w$ 等于训练时的窗口尺寸,RoPE 的位置取值就永远落在训练分布内,不存在外推问题。对比全注意力 + RoPE 的直接外推(训练 4k 推理 32k 必崩),SWA 在长度方向上是自带免疫的。

KV cache 淘汰也因此变得安全:淘汰位置 $j < i - w$ 的 KV 不影响任何未来查询——未来查询的相对距离仍然落在 $[0,w)$,被查询的位置都在窗口内。全注意力 + RoPE 做淘汰就没有这个性质,淘汰留下的是绝对下标断档,而幸存 token 之间的相对距离照样会超出训练分布(第 5150 篇的分辨率分析在这里直接适用)。

坑一:窗口尺寸不一致

一致性是相对于训练时那个 $w$ 而言的。把推理窗口从 $w$ 扩到 $2w$(为了多看点上下文),窗口内的相对距离就到了 $[0, 2w)$——RoPE 面对的全是训练没见过的位置取值,和全注意力外推是同一个病。Mistral 系模型后期版本做窗口扩展时,都要配套 RoPE 频率缩放(NTK-aware)加继续训练,不是改一行 config 就能扩。

反过来缩窗口没问题($[0, w/2) \subset [0,w)$)。一句话:宁小勿大。

坑二:混合层架构的 cache 语义

Gemma 2、Mistral 这类模型不是纯滑窗:层间交替"滑窗层 + 全局层"(稀疏模式的谱系见第 4130 篇)。注意两类层的 cache 需求完全不同:

$$ \text{滑窗层:只需保留 } [i-w,\,i] \text{ 的 KV,可淘汰;}\qquad \text{全局层:任意距离可达,KV 一个都不能丢。} $$

部署时如果按滑窗层的逻辑给全局层也做淘汰,远程依赖直接断掉;如果按全局层的标准全留,滑窗层省下的显存又全还回去。正确做法是分层管理 cache:按每层的 attention pattern 配置不同的 eviction 策略。另一个细节:滑窗层的窗口边界 token 容易长成新的 attention sink(StreamingLLM 正是利用这一点做流式推理)——sink 是淘汰策略必须豁免的对象,"最老的不淘汰"这种一刀切规则在这里会出错。

坑三:流式切块的坐标系

长输入流式处理(chunked prefill)时,若图省事让每个 chunk 从位置 0 重新计数 RoPE,滑窗层在 chunk 边界处看到的相对距离就是错的:位置项本应给出"这两个 token 相距 3000",现在给出"相距 40"。chunk 大小 $c > w$ 时错误被掩盖(窗口根本不跨界),但 $c < w$ 时边界两侧的相对距离系统性失真,生成会出现重复、断裂。规矩只有一条:RoPE 的位置永远用全局绝对下标,切块只切计算,不切换坐标系。

小结

SWA × RoPE 是天作之合还是埋雷现场,取决于三个"一致":窗口尺寸与训练一致、分层 cache 策略与层的 pattern 一致、流式坐标与全局下标一致。三条都满足时,这套组合是长文本推理里最省心的方案之一;破任何一条,症状都长得像"模型突然变傻",排查按这个清单走能省一半时间。

滑窗 + RoPE:窗口内相对距离恒落在 [0, w),超出部分已淘汰 0 1 2 3 4 5 6 7 8 9 10 11 窗口 w=4 左侧 KV 已淘汰 滑窗层:相对距离 ∈ [0, w) RoPE 位置取值永不出训练分布 全局层(混排时):KV 不可淘汰 坑:推理 w′ > 训练 w ⇒ 外推病 坐标系纪律:切块 / 流式只用全局绝对下标,切计算不切换坐标系