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 稳。

常见追问

  1. SWA 的窗口大小怎么选?大模型一般取 4K 是怎么定的?
  2. SWA 配合 RoPE 时位置编码怎么处理?窗口移动后是否需要重新算?
  3. 为什么 Mamba 这类 SSM 能做到 O(n) 复杂度?它和 Sparse Attention 是什么关系?