Sliding Window Attention 的原理和局限是什么?
简化版
Sliding Window Attention 让每个 token 只关注附近 W 个位置,把标准注意力的时间/显存复杂度从 O(n²) 降到约 O(nW)。多层堆叠后信息可逐层跨窗口传播,但远距离联系路径变长,单层无法直接访问全局证据。它适合局部相关强的长序列,通常需配合少量全局 token、跨层模式或检索;窗口大小要按任务质量、KV/延迟和硬件 kernel 实测。
详细版
因果滑窗中位置 i 通常只能看 [max(0,i-W+1), i],双向编码器则看左右邻域。注意力连接数由 n² 变为约 nW,当 W≪n 时节省显著。
n=32768, W=2048
full edges ≈ 1.07B
window edges ≈ 67M,约为 full 的 1/16
但理论稀疏只有在推理/训练内核不计算被屏蔽块时才加速。层数 L 可扩大有效感受野,粗略上限约 L×W,但信息需多跳传递且会衰减。评测要包含局部任务、长距离检索、多跳组合、序列边界和真实硬件延迟,不能只用短文本平均分。
完整版教学
一、标准注意力为什么难扩长
长度 n 的每个 query 与 n 个 key 计算,注意力分数矩阵有 n² 个元素。序列从 4K 增至 32K,矩阵元素增长 64 倍。
Sliding Window 假设大多数依赖是局部的,只保留对角线附近连接,把无关远距离边直接不计算,而不仅是算完再 mask。
记忆钩子:滑窗省的是“每个 token 看全班”,改为“只看附近同学”;代价是远处消息要层层传话。
二、因果窗口如何构造
自回归位置 i 只能访问自己和前 W-1 个 token:
visible(i) = {j | max(0, i-W+1) <= j <= i}
W=4 时,位置 6 可看 3、4、5、6,不能看位置 2。序列开头窗口自然缩小,不应循环到末尾。
双向模型可取左右各 W/2,但边界、奇偶窗口定义要在实现与论文比较中说明。
三、复杂度与显存收益
每个位置最多连接 W 个 key,因此 score 计算约 nW。当 n=16K、W=1K 时,连接数约为全注意力的 1/16。
| 方案 | 连接数 | 长距离访问 |
|---|---|---|
| Full Attention | O(n²) | 单层直接 |
| Sliding Window | O(nW) | 多层间接 |
| Window + Global | O(nW+ng) | 通过 g 个全局 token |
训练激活显存通常下降;生成时 KV Cache 是否同步缩短取决于模型实现和是否只保留窗口内 KV。
四、多层会扩大感受野
第一层每个 token 看 W 范围,第二层读到的表示已经包含邻居信息,因此理论感受野随层数扩展。若单侧窗口跨度 W-1,L 层可传播约 L(W-1) 距离。
这不等同于单层直接注意。远距离事实经过多次非线性与残差传播,精确信息可能衰减,且需要足够层数才能到达。
因此“层数×窗口覆盖全文”不能保证长距离检索准确率与 full attention 相同。
五、局部任务为何适合
自然语言相邻 token、音频局部帧和代码附近语法往往强相关,窗口可保留大部分有用连接。模型还能借残差和多层逐渐形成更广语义。
但文档开头规则约束末尾回答、跨章节实体关联和 needle retrieval 需要远距离联系。窗口太小时,末尾根本无法在有限层内获得开头信息。
任务结构决定窗口,而不是上下文标称长度决定窗口。
六、全局 token 与混合层补长程
可以让特殊 token 被所有位置访问,作为全局信息枢纽;也可每隔若干层使用一次 full attention,或让不同层窗口错位/扩张。
local tokens <-> window neighbors
\------> global tokens <------/
全局 token 数 g 较小时额外复杂度约 O(ng)。哪些 token 全局化要有语义依据,否则它们可能成为拥塞瓶颈。
RAG 是另一条路线:不让模型在全文内部传播,而是先把远处相关片段检索到当前窗口。
七、训练长度与推理模式要一致
模型若训练时使用某窗口,推理突然扩大窗口不一定有效;缩小则会切断训练时依赖的连接。位置编码和窗口模式共同决定长上下文行为。
KV Cache 滚动淘汰时,要保留特殊全局 token 和正确绝对位置。错误重置 RoPE 位置会让模型把新旧 token 的相对关系算错。
序列跨块生成还需验证边界 token,避免 off-by-one 导致实际窗口 W±1。
八、真实加速依赖稀疏 Kernel
若先计算完整 n×n 矩阵再用 mask 屏蔽,复杂度仍是 O(n²)。只有 block-sparse、FlashAttention 滑窗实现或专用 kernel 跳过无效块,才有理论收益。
窗口不是硬件友好块大小的整数倍时可能浪费;小序列下 kernel 启动与数据搬运会掩盖收益。应测 TTFT、吞吐、峰值显存和不同 batch/长度,而非只算 FLOPs。
正确性上比较专用 kernel 与朴素 mask 的输出和梯度,在容差内一致。
九、常见误区与追问
- 误区:滑窗 mask 后复杂度自然是 O(nW)。 若仍算完整矩阵,只是语义稀疏而非计算稀疏。
- 误区:多层覆盖全文就等于 full attention。 信息需多跳传播,精度与路径不同。
- 误区:窗口越大越好。 成本随 W 线性增长,需看任务边际收益。
- 误区:KV Cache 一定只需保留 W。 全局 token、混合层和实现可能要求更多缓存。
- 误区:长上下文标称长度证明远距能力。 必须测位置与距离分桶性能。
- 追问:窗口大小如何选? 依据依赖距离分布和质量—延迟—显存曲线。
- 追问:如何补全局信息? 全局 token、周期 full layer、扩张窗口或检索组合。
- 追问:怎样测试边界实现? 与全矩阵参考对比,覆盖开头、结尾和 KV 滚动位置。
十、加强记忆
Sliding Window Attention 记住“n² 变 nW、局部直接看、远处逐层传”:因果位置只看最近 W 个 key,多层扩大理论感受野却不等价于全连接;全局 token、混合层和 RAG 可补长程依赖。只有稀疏 kernel 真正跳过无效块才加速,窗口选择必须用远距任务质量、TTFT、吞吐与缓存显存共同验证。