21. Sliding Window Attention 和 Sparse Attention 有什么区别?分别在什么场景下用?
整理 SWA、Sparse Attention 等稀疏注意力方案的差异与适用场景。
简单回答
Sliding Window Attention(SWA)是 Sparse Attention 的一种特例。Sparse Attention 是个总称——所有"让每个 token 只关注一部分 token 而非全部 token"的注意力都属于稀疏注意力。SWA 的形式最简单:每个 token 只关注它前面固定窗口大小(比如 4096)的 token,超出窗口的就不管了。其他典型 Sparse Attention 形式还有 dilated(按固定间隔跳过)、global token(少数 token 全连接)、block sparse(按块分组)等。SWA 适合"局部依赖足够、长程依赖通过堆叠层间接获取"的场景,Mistral 7B、Gemma 都用。复杂的 Sparse Attention 模式(如 Longformer、BigBird)则在长文本任务上做更精细的取舍。
详细解释
标准 Self-Attention 的代价
普通 Self-Attention 的计算复杂度是 ,n 是序列长度,d 是隐层维度。这意味着序列翻倍则计算量和显存占用都翻 4 倍。在 32K、128K、1M 这种长上下文场景下,O(n²) 直接成了硬墙——本专题第 14 篇讲的 FlashAttention 能加速但改变不了量级。
Sparse Attention 的核心动机就是:很多任务里其实不需要每个 token 都和所有其他 token 算注意力,让每个 token 只看相关的一部分 token,复杂度可以降到 (k 是每个 token 关注的 token 数)。
Sliding Window Attention(SWA)
SWA 的规则极其简单:每个位置 i 只关注 i - w, i 范围内的 token,w 是窗口大小(比如 4096)。窗口外的全部不看。
这样每个 token 的注意力只算 w 个对,总复杂度从 O(n²) 降到 O(n·w),在 n >> w 的场景下大幅降低。Mistral 7B 用的就是 SWA(窗口 4096),Gemma 也用了变体。
但表面看 SWA 有个明显问题——它怎么获取远距离的依赖?比如序列 100K,窗口 4K,那第 100000 个 token 永远看不到第 1000 个 token?
答案是通过层间接传递。第 1 层 token 100000 看 96000, 100000;这些位置在第 1 层已经看过 92000, 96000 了;所以到第 2 层,token 100000 间接获取了 92000, 100000 的信息;以此类推 L 层之后能间接覆盖到 L·w 距离。一个 32 层的模型加 4K 窗口,理论感受野是 128K——足够多数任务用了。
代价是远距离信息传递不直接、信号会衰减。SWA 在严格依赖远距离精确细节的任务(比如长文档里精确定位某个数字)上会比 Full Attention 弱。
其他 Sparse Attention 模式
Dilated(膨胀)窗口:每个 token 不连续地看附近,而是按固定间隔跳着看——位置 i 关注 i, i-1, i-2, i-4, i-8 ... 这种指数递增的间隔。能在更小的预算下覆盖更远的距离。
Global Token:让少数特殊位置(比如 CLS、问题部分的 token)做全连接,其他位置只做 SWA。这样一些"关键节点"能直接看到全局信息,避免完全依赖层间传递。Longformer 就是 SWA + global token 的组合。
Block Sparse:把序列按块分组(比如每 64 个 token 一块),每个块里 full attention,块和块之间按某种稀疏模式(每隔 k 块连接一次或随机采样)连接。BigBird 是这个思路的代表。
Random + Local + Global:BigBird 论文里提到的混合方案——每个 token 看局部窗口 + 几个全局 token + 一些随机 token。理论上能保证近似全连接的表达力。
这些更复杂的 Sparse Attention 在追求"长上下文 + 精确远距离依赖"的任务上比纯 SWA 表现好,但 kernel 实现复杂度也高得多——不规则的稀疏模式不容易写出高效的 GPU kernel,实际推理速度收益不一定线性。
现代大模型为什么很多回到 Full Attention
有一个值得注意的事实:早年(2020-2022)大量论文在做各种 Sparse Attention,但 2023 年之后主流大模型反而很多走回 Full Attention 了——LLaMA、Qwen、DeepSeek、GPT-4o 都是 Full Attention 配本专题第 06 篇讲的 RoPE 和第 14 篇讲的 FlashAttention。
原因有几个。FlashAttention 大幅降低了 Full Attention 的实际计算开销,O(n²) 在 32K、64K 范围内已经不是瓶颈。Full Attention 在长程精确依赖上的表达能力优势是真的——很多 long-context benchmark 上稀疏方案都比 full 弱一截。RoPE 等位置编码扩展手段让 Full Attention 也能做到 100K+ 上下文。
Sparse Attention 在两类场景仍然很有用:一是部署侧极度受限的小模型(Mistral 7B 用 SWA 是为了在边缘设备上跑长上下文);二是真正需要 1M+ 超长上下文的场景(这时 Full Attention 还是吃不消,比如 Gemini 1.5 用了 mixture of experts + 各种稀疏化技巧)。
KV Cache 的影响
SWA 还有一个被低估的好处——KV Cache 显存。Full Attention 要保留所有历史 token 的 KV,长上下文下 KV Cache 可能比模型权重还大。SWA 只需要保留窗口内的 KV,超出窗口的可以丢,KV Cache 显存固定为 O(w) 而不是 O(n)。
这对边缘部署和长对话场景特别有价值——一个对话跑了几小时,用 SWA 的话 KV Cache 不会无限膨胀。但代价同样是远距离信息丢失,超出窗口的内容真的"忘了"。
选择的逻辑
要做工程选型,就看任务对"远距离精确依赖"的需求强度。
- 主要做局部任务(代码补全、短文本对话、工具调用)——SWA 完全够用,且省显存。
- 长文档理解、跨段落推理、引用追溯——倾向 Full Attention + RoPE 扩展。
- 超长上下文(百万级 token)——必须做某种稀疏化,但不一定是 SWA,更复杂的 hybrid 模式(SSM + Attention 的混合,如 Mamba/Jamba)也是选项。
面试时可以这样答
Sliding Window Attention 是 Sparse Attention 的一种特例。Sparse Attention 是个大类——所有让每个 token 只看部分 token 而非全部的注意力变体都算。SWA 形式最简单:每个 token 只看前面固定窗口比如 4K 的 token,超出的不管。复杂度从 O(n²) 降到 O(n·w)。
SWA 看起来不能获取远距离依赖,但实际通过层间传递间接覆盖——一层窗口 w,L 层后理论感受野 L·w。32 层 4K 窗口理论上够 128K。代价是远距离信号会衰减,长程精确依赖比 Full Attention 弱。
其他常见 Sparse Attention 形式还有 dilated(按指数间隔跳着看,更广覆盖)、global token(少数 token 全连接做关键节点)、block sparse(按块分组,块内 full 块间稀疏)。Longformer、BigBird 是这些思路的代表。
一个反直觉的事实是 2023 年之后主流大模型很多走回了 Full Attention——LLaMA、Qwen、DeepSeek 都是。原因是 FlashAttention 把 Full Attention 的实际开销降下来了,长程依赖表达上 Full 仍然有优势。Sparse Attention 现在主要用于两类场景——边缘部署受限的小模型(Mistral 用 SWA)和真正百万级超长上下文(这时 Full 也吃不消)。
工程选型上看任务对远距离精确依赖的需求——以局部为主用 SWA 能省显存省 KV Cache,跨文档跨段落推理还是 Full Attention 稳。
常见追问
- SWA 的窗口大小怎么选?大模型一般取 4K 是怎么定的?
- SWA 配合 RoPE 时位置编码怎么处理?窗口移动后是否需要重新算?
- 为什么 Mamba 这类 SSM 能做到 O(n) 复杂度?它和 Sparse Attention 是什么关系?