Flash Attention:IO-Aware 的注意力计算优化
18 Flash Attention:IO-Aware 的注意力计算优化
算法 Leader 每日深入简述 · 第 18 天 GPU 算力每年翻倍,但显存带宽增长缓慢——attention 的真正瓶颈不是 FLOPs,而是 HBM 读写。Flash Attention(Tri Dao, 2022)抓住这点,用分块(tiling)和重计算(recomputation),让 attention 计算尽量在 SRAM 内完成,避免中间
n × n矩阵落盘 HBM。它在数学上等价于标准 attention,但实际速度提升 2-4 倍、显存从 O(n²) 降到 O(n)。Flash Attention 已是 PyTorch 2.0+ 默认实现,是训练与推理的事实标准。
一、算法概览
Flash Attention 是一种 IO-Aware 的注意力计算优化算法,核心思想是通过分块(tiling)和重计算(recomputation),让 attention 计算尽量在 GPU SRAM(片上高速缓存)中完成,减少对 HBM(高带宽显存)的读写。它在数学上精确等价于标准 attention(非近似),但实际速度提升 2-4 倍,长序列场景显存从 O(n²) 降到 O(n)。后续 Flash Attention v2/v3 进一步优化并行度与异步拷贝。PyTorch 2.0 起 F.scaled_dot_product_attention 默认调用 Flash Attention。
二、历史背景与问题起源
2.1 GPU 算力与带宽的剪刀差
Transformer 自 2017 年诞生后,attention 的 O(n²) 计算复杂度一直是心头大患。但 2020 年前后 GPU 算力飞速增长(A100 算力 312 TFLOPS、H100 算力 1000+ TFLOPS),瓶颈其实从 FLOPs 转向了显存带宽:A100 HBM 带宽约 2TB/s,SRAM 带宽约 19TB/s——差近 10 倍。标准 attention 先把 n × n 的 attention 矩阵写入 HBM,再读回来做 softmax 和加权求和,HBM 读写量达到 O(n²·d),被带宽卡死。
2.2 Tiling 思想与 IO 复杂度
经典 GPU 优化中,分块(tiling)是把大矩阵切成小块加载到 SRAM 计算的通用技术。Tri Dao 和 Guolini 2022 年把它专门应用于 attention,关键难点是 softmax 需要全局归一化——必须算出全行 max 与 sum 才能归一化。他们用 online softmax(分块计算 max 和 sum,逐步归一化)破解这个难题。
2.3 Flash Attention 的演进
Flash Attention v1(2022)确立 tiling + 重计算框架;v2(2023)优化 warp 级并行与 GPU 占用率,速度再提升 2 倍;v3(2024)针对 H100 的异步拷贝(TMA、WGMMA)做深度优化,FP8 支持下推理速度比 v2 快 1.5-2.5 倍。同期 xFormers 的 memory_efficient_attention 提出类似思路,Flash Attention 因开源活跃、性能领先成为主流。
三、核心原理深入
3.1 直观类比:炒菜的灶台与冰箱
你在炒一大锅菜,灶台旁边的小砧板是 SRAM(快但小,约 192KB/SM),大冰箱是 HBM(慢但大,80GB)。笨办法是先把所有菜从冰箱搬到砧板,切完再搬回冰箱,再取出来炒——来回搬菜浪费时间。聪明做法是每次只取一小撮菜,在砧板上切完直接下锅,中间结果不回冰箱。Flash Attention 就是后者。
3.2 标准 Attention 的 IO 问题
标准 attention 流程:
S = Q · K^T # n × n 矩阵,写入 HBM
P = softmax(S) # n × n 矩阵,读 S 写 P
O = P · V # n × d 矩阵,读 P 写 O
中间矩阵 S、P 都是 n × n,对长序列极耗显存带宽。n=8192, d=128 时,S 单个就要 256MB,多次读写 HBM 总量达数 GB 级。
3.3 Flash Attention 的两步关键创新
1. Tiling(分块):把 Q、K、V 切成块,逐块加载到 SRAM,分块计算部分 attention 并累积结果。难点是 softmax 需要全局最大值和归一化因子,于是采用 online softmax(分块计算 max 和 sum,逐步归一化):
# 对第 i 块 Q,遍历所有 K、V 块 j
s_ij = Q_i · K_j^T # 在 SRAM 内计算
m_new = max(m_old, rowmax(s_ij)) # 更新行最大值
p_ij = exp(s_ij - m_new) # 用新 max 归一化
l_new = exp(m_old - m_new) · l_old + rowsum(p_ij)
o_new = (exp(m_old - m_new) · o_old + p_ij · V_j) / l_new
每块算完直接累加到输出 O,从不把完整 S 或 P 写回 HBM——这就是节省 IO 的核心。
2. Recomputation(重计算):反向传播需要中间结果,标准做法是缓存 P(n² 显存)。Flash Attention 选择不缓存,反向时用保存的 Q、K、V 和归一化统计量 (m, l) 重算 attention,节省显存而 FLOPs 只多 1/3。由于反向是 compute-bound,多算的 FLOPs 被 IO 节省抵消还有余。
3.4 IO 复杂度对比
设 SRAM 大小为 M:
- 标准 attention HBM 访问:O(n²·d + n·d²)(多次读写 S、P)
- Flash Attention HBM 访问:O(n²·d² / M)(分块后 IO 大降)
M 越大节省越多。A100 SRAM 约 192KB,n=8192, d=128 时 Flash Attention 的 HBM 访问比标准少约 10 倍——这就是 2-4 倍加速的来源。计算量都是 O(n²·d),但实际墙钟时间显著下降。
四、训练/推理流程
训练:直接替换 attention 实现,对用户透明。前向分块计算并保存 (m, l),反向重算 attention。通常加速 2-3 倍,长序列(如 8K、32K)增益更大。PyTorch 2.0 后 F.scaled_dot_product_attention 默认调用 Flash Attention,无需手动改代码。注意:要充分发挥 FA 优势,输入张量需在最后一个维度 causal mask 对齐,且 batch 不能过于碎小。
推理:分两阶段看。
- Prefill 阶段(一次处理 prompt):受益最大,Q 有多行可并行分块。
- Decode 阶段(每步只生成 1 个 token,Q 只有 1 行):Flash Attention 增益有限,因为此时瓶颈是 KV Cache 读取而非中间矩阵。需要 Flash Decoding 等变种专门优化——把 K/V 沿序列维度分块并行计算,最后 reduce。
五、与其他算法的关系
- 与 KV Cache:Flash Attention 是单步 attention 计算优化,KV Cache 是跨步复用,二者正交。推理框架通常联合使用。
- 与 Sparse / Linear Attention:稀疏/线性 attention 改变数学形式降低 O(n²),Flash Attention 不改变数学只优化 IO。前者有精度损失,后者精确等价。可叠加(如 BlockSparse Flash Attention)。
- 与 PagedAttention:PagedAttention 管 KV Cache 显存布局,Flash Attention 管计算 IO,可叠加。vLLM 默认组合二者。
- 与 xFormers / memory_efficient_attention:思路类似,Flash Attention 是最知名且持续演进的实现。
- 与 MQA/GQA:结构层面的 KV 压缩,与 Flash Attention 正交,可同时启用。
六、关键论文与引用
| 论文 | 年份 | 核心贡献 | 链接 |
|---|---|---|---|
| FlashAttention: Fast and Memory-Efficient Exact Attention | 2022 | IO-Aware tiling + 重计算 | https://arxiv.org/abs/2205.14135 |
| FlashAttention-2 | 2023 | 优化并行度与 warp 调度 | https://arxiv.org/abs/2307.08691 |
| FlashAttention-3 | 2024 | 异步拷贝与 FP8 支持 | https://arxiv.org/abs/2407.08608 |
| Flash-Decoding | 2023 | decode 阶段并行优化 | https://arxiv.org/abs/2310.01877 |
| xFormers memory_efficient_attention | 2022 | 同期类似方案 | https://arxiv.org/abs/2207.10884 |
| BlockSparse Flash Attention | 2023 | 稀疏+Flash 结合 | https://arxiv.org/abs/2305.11679 |
七、实践思考(Leader 视角)
作为 Leader,Flash Attention 是我评估训练基础设施的"基础项"——它不需要改训练逻辑,几乎零成本提升 2-3 倍 attention 速度和显存,任何新项目默认启用。但要注意:1) 短序列(n<512)增益不明显,因为标准 attention 已经够快;2) decode 阶段不是 silver bullet,需要 Flash Decoding 等专门方案;3) 不同硬件(A100 vs H100 vs AMD MI300)实现差异大,需要针对性编译;4) FP8 Flash Attention v3 在 H100 上能再快 2 倍,但精度需验证。强烈建议团队使用 PyTorch 2.0+ 的 SDPA 接口,让框架自动选最优 kernel,避免硬编码。
常见误区:
| 误区 | 事实 |
|---|---|
| Flash Attention 是近似算法 | 数学上精确等价,只是 IO 优化 |
| 长序列一定快 | 短序列启动开销可能反而更慢 |
| 反向更慢 | 反向 FLOPs 多 1/3 但 IO 大降,总耗时更短 |
| 推理也大幅加速 | 主要加速 prefill,decode 增益小 |
| 与 KV Cache 二选一 | 二者正交,可叠加 |
下期预告
下一篇:19 — Speculative Decoding:投机解码加速推理。我们将看到如何用小模型"猜"多个 token,再用大模型一次并行验证,把解码从顺序的 K 步压缩到 1-2 步,且数学上严格无损——输出分布与原大模型完全一致。