← 返回深度解读总览

FlashAttention-2 深度解读报告

论文:《FlashAttention-2: Faster Attention with Better Parallelism and Work Partitioning》
作者:Tri Dao(Princeton University CS & Stanford University CS)
技术报告(2023-07-18 落款);arXiv:2307.08691v1 [cs.LG](2023-07-17 提交;后见于 ICLR 2025)
开源:https://github.com/Dao-AILab/flash-attention
数据口径:本文所有数字与主张均严格依据同目录《00-源数据提取.md》提取结果;凡属本文在源数据基础上的衔接与展开推理,标注「(推断)」。

摘要(300 字)

FlashAttention 虽已通过 tiling、online softmax 与重计算实现精确注意力且将内存由二次方降为线性,并取得 2–4× 加速(Dao et al., NeurIPS 2022),但它的内核效率仍远低于 GEMM:在 A100 上仅达到理论峰值的 30–50%(前向)与 25–35%(反向),而优化 GEMM 可达 80–90%。本作《FlashAttention-2》不改动任何数学输出,而是专注三项工程性改进:其一,削减非矩阵乘(non-matmul)FLOPs——在 A100 上单个非 matmul FLOP 的成本约为 matmul 的 16 倍(FP16/BF16 matmul 理论 312 TFLOPs/s 对非 matmul FP32 19.5 TFLOPs/s),作者通过延迟缩放与仅存储 logsumexp 将非 matmul 工作最小化;其二,重排并行策略,前向后改按序列长度维(行块)并行以解决长序列小 batch 时的低占用率问题,反向按列块并行并用原子加聚合 dQ;其三,warp 级工作重划分,放弃前向的 split-K,改为按 Q 切分、K/V 全 warp 共享,彻底消除 warp 间通信。结果:A100 前向达 73% 理论峰值(230 TFLOPs/s)、反向 63%,整体相对 FlashAttention 加速 1.7–3.0×,相对 Triton 1.3–2.5×,相对 PyTorch 标准 3–10×;GPT-style 端到端训练 8k 上下文下达 72% 模型 FLOPs 利用率(225 TFLOPs/s),较无 FlashAttention 基线提速 2.8×;且在 H100 上不改代码即获 335 TFLOPs/s,验证算法可移植性。(推断:作为一次纯工程内核优化,它为后续「同价训练更长上下文」与 FlashAttention-3 的硬件专用特性利用铺平道路。)


一、问题定位:为什么 FlashAttention 还不够快

1.1 长上下文是刚需,但注意力成为瓶颈

论文开篇以长上下文的最新需求立论(§1 p1):GPT-4 支持 32k 上下文、MPT 65k、Claude 100k。标准注意力实现的时间与内存复杂度均为 O(N²)。当序列长度 N 扩展一倍,计算量与中间显存按平方增长,而海量中间矩阵 QK^T 与 softmax 结果(S、P)需落回 HBM,成为内存带宽的瓶颈。

FlashAttention 第一代已经解决了「内存」问题——通过分块(tiling)、online softmax 与反向重计算,把额外内存从 O(N²) 降到 O(N),并取得 2–4× 加速(§1 p2)。表面上这已经「够用」,但作者指出一个被忽略的关键事实(§1 p2):

FlashAttention 的运行速度仍远低于优化好的 GEMM 内核。

1.2 真正的短板:不是算法,而是「利用率」

问题被精准地重新定义为「计算效率」,而非「算法正确性」。具体数字见 Abstract p1 与 §1 p2:

也就是说,FlashAttention 的计算吞吐与「标准 GEMM」之间有一道约 1.7–2.7× 的缺口。既然注意力本身拆解开来就是若干 GEMM(QK^T、softmax、PV),为什么最终效率差这么多?答案指向线程块与 warp 之间的工作划分(work partitioning)次优——要么占用率过低(GPU 闲置的 SM 太多),要么为协调各 warp 付出了额外的共享内存读写与同步开销。

1.3 问题的双层结构

(推断)据此可以把问题拆为两层:

  1. 「怎么做计算」——算法/数学层面:第一代已解决(精确、线性内存),无需再动。这是 FlashAttention-2 明确「不改输出、不做近似」的原因。
  2. 「在哪里做计算」——硬件调度层面:FlashAttention-2 的所有改动都聚焦于此。论文把「速度快不快」归因于 GPU 微架构上的工作分区,而不是数学上的运算次数。

这个定位是整篇文章的核心气质:它是一篇工程内核论文,而非算法创新论文。作者明确说「输出与 FlashAttention 及标准注意力完全一致」(§3.1.1 p7,C9),从而把全部注意力(pun intended)放在「让相同的数学更快被算出来」。


二、概念内核:把「快算」的物理本质讲透

2.1 前提:GPU 上 matmul 与非 matmul 的成本相差悬殊

要理解 FlashAttention-2 的改法,先要建立一条核心认知(§3.1 p5,C2):

运算类型A100 理论吞吐相对成本
---------
FP16/BF16 matrix multiply312 TFLOPs/s基准 1×
非 matmul(FP32 标量/内存型运算)19.5 TFLOPs/s约 16×

也就是说,在 A100 上做一次「非矩阵乘」浮点运算的实际代价 ≈ 做 16 次「矩阵乘」运算。softmax 的 exp、归一化、逐元素缩放、以及中间结果的反复读写——这些恰恰属于昂贵的「非 matmul」部分。

结论非常直接:要想逼近 GEMM 效率,就必须把非 matmul 的 FLOPs 尽量削减到零。FlashAttention-2 的全部算法性改动(§3.1),本质上都是为了「少做非矩阵乘的事」。

2.2 第一代价:非 matmul FLOPs(在算法层面削减)

改动一:延迟缩放(delayed/divided scaling)。

FlashAttention 的 online softmax 在每一轮迭代中都需对累计的输出做重缩放——因为每来一个新 chunk,softmax 的归一化分母 ℓ^{(j)} 都在变,之前已算出的部分输出必须被重新缩放。这个「每轮都缩放」的动作是纯非 matmul 运算,且被反复执行。

FlashAttention-2 的做法(§3.1.1 p5-6):不再在每次迭代中缩放,而是维护一个「未缩放」的输出 Õ,只保存统计量(行最大值与行求和),等整个 outer loop 结束后,再做一次性全局缩放:

`

O_i = diag(ℓ^{(Tc)})^{-1} · Õ_i (循环结束后一次性执行)

`

这样把「N 次重复缩放」压缩为「1 次缩放」,把昂贵的非 matmul FLOPs 移出内层循环。

改动二:只存一个 logsumexp。

FlashAttention 反向需要 softmax 分母信息,第一代同时保存了 m(行最大值)与 ℓ(行求和,即 exp 和)。FlashAttention-2 发现真正需要的只是二者组合出的一个标量:

`

L = m + log(ℓ) (logsumexp)

`

反向传播时直接用 P = exp(S − L) 即可(§3.1.2 p6),不必再额外保存 m 与 ℓ 两个向量。这既省了存储,也省了反向中读取与重算这两个统计量的非 matmul 开销。

净效果(C9):输出与标准注意力逐位一致(no approximation),时间复杂度仍是 O(N²·d),额外内存为 O(N)——只存 logsumexp L。

2.3 第二代价:算法之外,还有「调度与通信」的开销

即使把非 matmul FLOPs 压到最低,GPU 内核仍有另一类浪费——线程为了协作而做的共享内存读写与同步等待,以及与「占用率不足」绑定的硬件闲置。这就是论文副标题「Better Parallelism and Work Partitioning」所指向的第二层问题。它无法靠改数学公式消除,只能靠重排「谁来算哪一块」来规避。

2.4 概念内核小结

(推断)用一句话概括 FlashAttention-2 的思维模型:

注意力 = 一组 GEMM + 一些软连接。GEMM 本身可以跑满 GPU;那些「软连接」(softmax、缩放、归一化、跨 warp 的数据搬运、不充分的并行)才是拖慢整体效率的东西。FlashAttention-2 = 把「硬计算」和「软开销」彻底分开,然后把软开销尽可能压掉。

这个视角解释了为什么它性能提升巨大却「只看硬件不看算法」——因为瓶颈本来就只在硬件侧。


三、方法拆解:三项工程改进的完整链条

3.1 背景回顾(§2 p3-5)

标准实现:计算 S = QK^T(一次 GEMM)→ 物化 S 到 HBM → softmax(S) → 物化 P 到 HBM → O = PV(第二次 GEMM)。问题:S、P 都是 O(N²) 的中间矩阵,全部落回 HBM,受内存带宽限制;反向还得把计算出的 P 存下来再做梯度。

FlashAttention(第一代):tiling 把 HBM 分块载入 SRAM,用 online softmax 边分块边算——维护 m(j) = rowmax 和 ℓ(j) = rowsum(e^{S−m}),输出按 diag(ℓ)^{-1} 缩放合并,避免中间矩阵落 HBM;反向在 SRAM 内重算 S/P,免存储。前向 2 个 matmul、反向 5 个 matmul(含重计算)。这套做法把内存从 O(N²) 降到 O(N),带来 2–4× 加速。

但如前所述,它远未跑到 GEMM 的效率水平(§2.3 的结论)。FlashAttention-2 在这套骨架上做三处手术。

3.2 手术一:削减非 matmul FLOPs(§3.1.1 p5-7)

(已在 §2.2 详述,此处补全伪代码与复杂度口径。)

改进后的 online softmax(前向,§3.1.1 p6)与 Algorithm 1 伪代码要点:外层按 Q 的行块遍历,内层维护已缩放的输出;循环结束后一次性缩放。Algorithm 2 反向伪代码:维护 P = exp(S − L),用存储的 logsumexp 而非两个统计量。

3.3 手术二:重排并行策略(§3.2 p7-8,C4)

前向:外层循环改为按序列长度(行块)遍历。原来的内层(按 head)并行维度保持,另叠加序列长度维,形成 batch × heads × seq-len 的三维并行。每个 thread block 独立处理一个 Q 行块,这是 embarrassing parallel(完全可并行、无需通信)。当序列很长而 batch·heads 很小(total thread block 数 < 108 SM,即 A100 的 SM 数)时,第一代会出现「GPU 大量空闲」的低占用问题;引入序列维并行后,占用率大幅提升。

反向:唯一跨列块共享的计算是 dQ 的更新。思路:按列块并行调度 thread block,dQ 用 atomic adds 跨块累加,从而也复用序列维并行。

(值得标注:交换内外循环并引入序列维并行的思路,由 Phil Tillet 在 Triton 实现中首创,本作将其吸收进 CUDA 内核。这是论文明确承认的来源——§3.2 p8。)

3.4 手术三:warp 级工作重划分(§3.3 p9,C5)

前向的差异最直观:

反向同样避开 split-K;但因为 Q/K/V/O/dO/dQ/dK/dV 之间的梯度依赖更复杂,仍需要少量同步,这也是反向峰值(63%)低于前向(73%)的原因之一。

Block size 调优:通常取 {64,128}×{64,128} 四种组合,在共享内存读写量与寄存器压力/spill 之间权衡,按 head dimension 手工选择。作者自认可引入 auto-tuning,留作 future work(§3.3 p9;§6 局限 1)。

3.5 附加:MQA / GQA 支持(§3.1.2 p7)

多查询注意力(MQA)与分组查询注意力(GQA)下,多个 query 头共享同一组 K/V 头。实现上不物理复制 K/V 头,而是隐式操作头索引;反向时对被隐式复制的头间做 dK、dV 求和。这是一处提升实用性的工程细节,让内核对 MQA/GQA 这种降低 KV 缓存/推理成本的注意力变体开箱即用。

3.6 方法全链条小结

把三处手术串起来——前向:块级跳 block + 延迟缩放 + 只存 logsumexp + 按序列并行 + Q 切分 warp 零通信;反向:按列并行 + atomic add 聚合 dQ + 用 L 重算 P + 避开 split-K。所有改动都不触碰数学输出(C9),却把 A100 前向推到 73% 理论峰值、反向 63%,相对第一代整体 1.7–3.0×。


四、证据链:从内核基准到端到端训练

4.1 基准口径(§4 p9-10)

4.2 内核基准证据(Figure 4/5/6,p10-12)

代表性数字(§5 要点 1):

设置FlashAttention-2FlashAttention 原版xformers/fastTriton
---------------
无因果掩码 d=128 前向223–22771–73122160–163
有因果掩码 d=64 前向171–18392–97——
反向 d=128 无掩码193–19684–88——
序列长 16k全程无 OOM———

要点:四组设置(±causal × head_dim 64/128)FlashAttention-2 全面领先。PyTorch 标准实现在 16k 序列直接 OOM,而 FlashAttention-2 全程无 OOM。

核心效率结论(C3):A100 前向最高 73%(230 TFLOPs/s)、反向最高 63% 理论峰值;整体相对 FlashAttention 1.7–3.0×、相对 Triton 1.3–2.5×、相对 PyTorch 标准实现 3–10×。

4.3 H100 迁移证据(Figure 7 p13,C8)

不改一行代码、未用新指令(未用 TMA / 第 4 代 Tensor Core / FP8)仅移植运行,即达 296–338 TFLOPs/s(前向+反向,无掩码),有掩码 d=128 达 308–328。作者预期若利用 H100 新特性可再 1.5–2×。这证明算法可移植性——提升不依赖特定硬件代际的「魔法」,而是可迁移的工作分区思想。

4.4 端到端训练证据(Table 1 p12,C7)

模型contextTFLOPs/s相对基线
------------
GPT3-1.3B2k / 8k196 / 220—
GPT3-2.7B2k / 8k205 / 225—
GPT3-2.7B 8k基线 80 → FA 175 → FA2 225——

对应口数字(§4 p10-11):单卡达 225 TFLOPs/s(72% model FLOPs utilization);较 FlA 最高 1.3×、较无 FA 基线 2.8×。8k 场景相对 FA 提升最大(170→220、175→225),印证长序列受益更多(C7)。

(推断:12.4 节「72% MFU」代表已相当接近「非注意力部分」的理论上限区间——因为非 attention 的 matmul 部分本身就受 16× 非 matmul 成本约束。剩余差距主要来自 softmax/exp 等非 matmul 运算与访存,见 §5 要点 4。)

4.5 证据链完整度小结

从「内核微基准」到「GPU 代际迁移」再到「真实训练吞吐」三层证据相互印证:第一层证明「单一 op 有多快」,第二层证明「思想可移植」,第三层证明「端到端真实收益」。三层都指向同一结论——FA2 在不改数学的前提下,把一个「远低于 GEMM 效率」的注意力内核提升到了「逼近 GEMM 效率」。


五、批判性分析

5.1 贡献的重新界定:工程 > 算法

这是本作最值得注意的一点。它不宣称新算法、不改 FLOPs 复杂度、不做近似(C9),一切收益来自「更好的硬件工作分区」。从学术「新颖性」角度看,这更像一篇系统/工程优化论文,而非方法创新论文。作者也坦然承认序列维并行思路来自 Phil Tillet 的 Triton 实现(§3.2 p8),因此其贡献应被准确定位为 「在 CUDA 内核里系统化地做完并验证了整套高效工作划分」,而非「发明了新的注意力算法」。

5.2 关键局限(§6)

  1. block size 靠手工调优(§3.3 p9):仅 4 种组合,需按 head dimension 与设备共享内存人工选择;作者自己提出应引入 auto-tuning,留作 future work。这使「快」依赖工程经验而非自动寻优,削弱了可复现/可迁移性。
  2. H100 专属特性未利用(§4.1 p11 / §5 p12):当前版本未用 TMA、第 4 代 Tensor Cores、FP8,H100 上还有 1.5–2× 预期提升。这部分收益被作者明确指向未来版(即后来的 FlashAttention-3),说明本作对最先进硬件的榨取并不完整。
  3. 反向仍有同步开销:虽避开 split-K,反向因梯度依赖复杂仍需少量 warp 间同步,反向峰值(63%)低于前向(73%)。这也暗示梯度回传部分还有进一步优化余地。
  4. 评测范围有限:基准限于 A100/H100、seq ≤16k、head_dim 64/128、GPT-style 语言模型训练;AMD GPU 支持列为计划而非实测;未报告推理/Prefill 场景与多模态形状。对「同价训更长上下文」的论断,作者只给出训练侧证据,推理侧(尤其长文本 inference 的 KV 缓存与 prefill)未系统评测。
  5. 对硬件的强依赖:全部收益建立在特定代际的微架构细节上(SM 数量、SRAM 容量、Tensor Core 吞吐比)。一旦换到不同硬件(如 AMD、推理专用加速器),同一套工作分区的收益需要重新调参与验证,可迁移性存在但代价未知。

5.3 隐藏的成本与「免费午餐」辨析

(推断)FlashAttention-2 看起来提供「免费午餐」——算得快、内存省、输出不变。但有两个容易忽略的隐形成本:

5.4 与其他快速注意力路线的比较

(推断,框架性判断)在 2023 年这个时间点上,快速注意力大致分两支:

这条对比能解释 FlashAttention 家族的「统治地位」:在训练场景,近似路线的精度风险不可接受,而精确路线的工程优化恰好能落地。FlashAttention-2 正是把「精确」的常数系数压到了接近 GEMM,从而在「用得起」上逼近了近似路线的吸引力。

5.5 批判性结论

FlashAttention-2 是一篇「把现有算法做到硬件极限」的教科书式工程作品。它的贡献真实(2–4× 加速、逼近 GEMM),但它的边界同样清晰(不动算法、依赖手工调参、依赖特定硬件)。它的价值更多体现在「为整个生态提供开箱即用的高性能注意力内核」,而非「提出新的计算范式」。


六、启示与影响

6.1 对「上下文长度」的直接现实意义(C10)

作者在 §5 p11 给出最具实际价值的论断:FlashAttention-2 快 2×,意味着用过去训练 8k 上下文的成本,现在可以训练 16k 上下文。这直接把「长上下文」从「昂贵的研究实验」推向「可负担的工程实践」。结合第一代 2–4× 加速,FlashAttention 系列让 transformer 在序列长度上可扩展了一个数量级。(推断:这也解释为何 GPT-4/Claude 等高上下文模型的训练成本能被压到可接受范围——注意力内核效率是其中关键一环。)

6.2 对硬件利用率的示范意义

论文反复强调一个被很多算法研究者忽视的事实:算法效率 ≠ 硬件利用率。即便算法时间复杂度已是 O(N²) 下限,GPU 实际吞吐仍可能只有峰值的 30%。FlashAttention-2 示范了「在不改算法的情况下,用正确的并行/分区策略把硬件吃满」,这一思想对任何 kernel 工程师都有普适参考价值。

6.3 对「非 matmul 成本」这一维度的强调

「非 matmul FLOP 贵 16 倍」这一洞察(C2),把注意力优化的注意力(p)从一个容易被忽视的角度拉了回来。它提醒研究者:现代 GPU 的算力分布极度不均,优化目标不应只是「减少运算次数」,更应是「把运算转换到便宜的硬件单元」。这种「按成本驱动的 kernel 设计」视角,已成为后续 FlashAttention-3、以及在 GQA、Mamba 等序列模型内核设计中的通用语言。

6.4 技术路线延伸与遗产

6.5 一句话总结

FlashAttention-2 没有改变「注意力算什么」,却彻底改变了「注意力怎么被算得这么快」——它用一个精妙的硬件工作划分,把一个只用满 30–50% GPU 的注意力内核,推到了 73% 的理论峰值,让「长上下文」从奢侈品变成了可负担的工程选项。


*本报告数据与主张均依据《00-源数据提取.md》,括号标注「(推断)」处为分析性衔接,非源数据直接表述。*

数据依据:本页 00-源数据提取.md | 推断处已标注(推断)| 生成:批量转换脚本