3.1 性能模型:用 Roofline 与算术强度算清为什么快


文档摘要

3.1 性能模型:用 Roofline 与算术强度算清“为什么快、为什么长序列更赚” 读者读完这一节,应该能回答一句:FlashAttention-2 的加速不是“玄学提速”,而是把注意力的算术强度从“带宽受限区”往“算力屋顶”抬了一截;而且因为朴素注意力的 HBM 往返成本随序列长度被平方放大,序列越长,这截抬升带来的相对收益就越大。 第 2 章讲 FA-2 时我们反复提到“把数据留在 SRAM、减少 HBM 往返”。这一节,我要把这句话变成一个你能手算的数字。否则它永远只是句漂亮话,遇到“我开了 FA-2 但只快了 10%”的情况,你没法判断是 FA-2 没生效、还是业务本身不在瓶颈上。 3.1.

3.1 性能模型:用 Roofline 与算术强度算清“为什么快、为什么长序列更赚”

读者读完这一节,应该能回答一句:FlashAttention-2 的加速不是“玄学提速”,而是把注意力的算术强度从“带宽受限区”往“算力屋顶”抬了一截;而且因为朴素注意力的 HBM 往返成本随序列长度被平方放大,序列越长,这截抬升带来的相对收益就越大。

第 2 章讲 FA-2 时我们反复提到“把数据留在 SRAM、减少 HBM 往返”。这一节,我要把这句话变成一个你能手算的数字。否则它永远只是句漂亮话,遇到“我开了 FA-2 但只快了 10%”的情况,你没法判断是 FA-2 没生效、还是业务本身不在瓶颈上。

3.1.1 Roofline 模型:先认领你的硬件“天花板”

理解一切加速的前提,是先知道硬件有两道天花板。以 A100 这类训练/推理卡为例(具体数字随卡而异,务必以你手上的官方规格为准):

  • 算力屋顶:约几百 TFLOPS 的浮点算力(fp16 下更高)。这是 GPU 乘法器的理论上限。
  • 带宽斜坡:HBM 显存带宽约 1.5~2 TB/s 量级。这是数据从显存搬到计算单元的速度上限。

Roofline 模型用一张图把这俩画出来:横轴是“算术强度”(每搬 1 字节数据能做的浮点运算数,单位 FLOPs/Byte),纵轴是“可达性能”。图的左下到拐点是一条斜率为带宽的斜线(带宽受限区,你被显存搬运速度卡着),拐点之后是一条水平线(算力受限区,你被乘法器卡着)。

Roofline 模型:算力屋顶与带宽斜坡

关键判断:一个算子落在斜线区还是水平区,决定了你该优化“搬运”还是“计算”。 朴素注意力几乎永远落在斜线(带宽受限)区——它算术强度太低,乘法器闲着,GPU 在干等数据从 HBM 慢慢爬上来。

3.1.2 注意力的算术强度:为什么它天生“贫血”

我们把一次标准稠密注意力(不考虑 FA 优化时)的算术量和访存量粗略算一下。设序列长度为 n,头维度为 d,头数为 h:

算术量(FLOPs)≈ 注意力本身的矩阵乘 ≈ O(n·d) 量级(多头合并后是 O(n·d·h) 但 h、d 是常数级) 访存量(Bytes)≈ 读写 Q/K/V/O 等输入输出张量 ≈ O(n·d) + 额外 KV Cache 读取,同样线性于 n

于是:

算术强度 = 算术量 / 访存量 ≈ O(n·d) / O(n·d) ≈ O(1)

结论很反直觉但很硬核:标准注意力的算术强度几乎不随序列长度 n 增长,是一个常数级的小数字。 它不像矩阵乘(大矩阵时算术强度很高、能吃到算力屋顶),而是“做一点点算、就要搬一堆数”的典型带宽受限算子。这解释了为什么你换更强的卡(算力屋顶更高)却没快多少——你根本没碰到天花板,你卡在斜坡上。

这里有个对比能帮你建立直觉:同样规模的数据,一个大的矩阵乘法(比如两个 [n, d] 乘 [d, n] 的矩阵)算术强度可以做到 O(d) 量级,d 越大越强,能爬上算力屋顶;而注意力里那些矩阵乘虽然也是“乘”,但输入输出张量 O(n·d) 相对算术量 O(n·d) 的“比值”很小,导致它天生贫血。换句话说,注意力是“被内存带宽掐着脖子”的算子,这正是 FA-2 死磕 HBM 往返的根本原因。

注意力算术强度不随序列长度增长的推导

给你的判断口诀:注意力不是“算力不够”,是“喂不饱算力”。优化方向永远是“少搬、多算”,而不是“换更猛的乘法器”。

3.1.3 FlashAttention-2 怎么把算术强度“抬”起来

第 2 章讲的核心:FA-2 用 tiling 把 Q/K/V 切成小块搬进 SRAM,在 SRAM 内完成“分数计算 + 在线 softmax + 乘 V”的融合,只把最终结果 O 写回 HBM。关键收益是大幅减少了 HBM 的往返次数——尤其是避免了把那张 O(n²) 的分数矩阵物化到 HBM 再读回来的两次大搬运。

从 Roofline 视角看,FA-2 的效果不是“让算力变高”,而是“让同样的算术量所需的 HBM 访问变少”,相当于把工作点沿着横轴向右推、靠近带宽斜坡的拐点,从而更充分地利用已经存在的带宽。换句话说:它把原来被“反复读写 HBM”白白消耗的时间省回来了,让真正有用的计算占比变高。

这里必须诚实地说一个边界:FA-2 不能把算术强度从 O(1) 变成 O(n)。 它的提升来自“减少 HBM 往返次数”与“算子融合减少冗余读写”,而非改变注意力的根本算术量。所以如果你期望“序列越长,绝对加速倍数无限放大”,那是不对的;但“相对收益随 n 变大而更显著”,这个判断成立,下一小节解释为什么。

为了把这件事说得更透,我给你一个手算小例子。假设 d=128,n=4096,fp16(2 字节):

朴素注意力要物化的分数矩阵 S ≈ 4096 × 4096 × 2 字节 ≈ 33.5 MB 再加上权重矩阵 P 同样大小,HBM 里光这两张中间矩阵就 ≈ 67 MB,且 全程要“写 S → 读 S 做 softmax → 写 P → 读 P 乘 V”,至少 4 次大块 HBM 往返。 FA-2 不物化 S/P,只把最终结果 O(4096×128×2 ≈ 1 MB)写回, 中间块全在 SRAM 流转,HBM 往返降到“必要的 Q/K/V/O 读写”量级。

注意这个例子的启示:n 翻倍到 8192,朴素那两张矩阵从 67 MB 涨到 268 MB(4 倍),HBM 往返的“等带成本”同步放大;而 FA-2 的 HBM 访问只随必要张量线性涨一点。 这就是 3.1.4 要量化的“相对收益随 n 放大”的微观来源。

3.1.4 为什么序列越长,FA-2 的相对收益越大

朴素注意力最大的问题是:那张分数矩阵 S 和权重矩阵 P 是 O(n²) 的。在朴素实现里,它们会被完整物化到 HBM。于是:

朴素实现的“HBM 往返 / 物化开销” ∝ O(n²) 的量级随 n 膨胀

而 FA-2 不物化这张矩阵,HBM 往返主要正比于必要的 KV 读取,增长平缓得多(逻辑上正比于序列相关的 O(n) 级访问,加上固定的输入输出)。把两者画成随 n 变化的曲线:朴素那条随 n² 陡升,FA-2 那条平缓。序列越短,两者绝对差还不大;序列越长,朴素那条被 n² 推得越高,FA-2 省下的相对比例就越大。

长序列下朴素与 FA-2 的 HBM 往返成本对比

一个常被误读的点要澄清:“长序列收益更大”说的是相对收益(FA-2 对比朴素的提速比),不是绝对耗时。 在 512、1024 这种短序列上,注意力本身就不是主要成本(kernel 启动、KV 读取占比高),FA-2 的提空间有限;一旦进入 4K、8K、32K 上下文,朴素实现的 O(n²) 物化开始主导耗时,FA-2 的价值才真正爆发。这也是为什么“长上下文模型 + FlashAttention”是天作之合。

3.1.5 可操作的性能测算方法(别只报“快了 2 倍”)

当你要证明某次优化有效,或者排查“为什么没快”,请按下面的清单走,结论才有说服力:

① 固定变量:模型、batch size、dtype、硬件都锁死,只扫序列长度这一个维度。 ② 两组对照:同一配置下分别跑“朴素注意力”与“FlashAttention-2”。 ③ 记录指标:tokens/s(吞吐)、峰值显存、首 token 延迟(TTFT)、以及 nvidia-smi / PyTorch Profiler 里的 HBM 带宽占用率和 SM 利用率。 ④ 画曲线:把吞吐随序列长度的变化画出来,看 FA-2 的收益在哪个长度开始显著。 ⑤ 下结论的范式:不写“快了 2 倍”,写 “在 >2048 长度后收益显著,4096 时吞吐提升约 Y%、显存下降约 Z%”。

需要特别说明的是第 ③ 步里的两个指标如何解读。HBM 带宽占用率如果长期贴近 90%~100%,说明你确实卡在带宽上,FA-2 的“减少往返”正中要害;如果带宽占用只有三成、但 SM 算力也闲着,那瓶颈可能根本不在注意力(比如在数据预处理、在 CPU 侧的 tokenize、在采样的解码循环里),这时优化注意力算法收效甚微,你该去 profiling 整个推理链路而非盯着注意力内核。这也是为什么我反复强调“先量再优化”——没量就优化,等于蒙眼修车。

判断该用哪种优化的决策小抄

这套方法的精髓在于:先定位瓶颈类型,再谈优化是否有效。 如果你的 profiling 显示 SM 利用率已经很高、带宽没打满,那说明你不在带宽受限区,FA-2 救不了你——这时该怀疑的是批大小、并行度、或者瓶颈根本不在注意力(比如在embedding、在通信、在采样逻辑)。反过来,如果带宽被打满、SM 闲着,而你又跑的是长序列,那 FA-2 几乎一定见效。

3.1.6 三个最常见的误解(以及正解)

在收尾前,我把读者最常被绕进去的几点拎出来,避免你掉坑:

  • 误解一:“FA-2 是换了个更快的算法,算得更快。” 正解:它主要不是在“算”上更快,而是在“搬”上更省。瓶颈在带宽而非算力时,省搬运才是关键。
  • 误解二:“序列越长,FA-2 绝对提速倍数越大。” 正解:谈的是相对收益(对比朴素的提速比)随 n 增大而更显著;绝对耗时仍然随 n 增长,只是朴素涨得更凶。
  • 误解三:“只要开了 FA-2,推理就一定能快一倍。” 正解:前提是你的瓶颈确实在注意力的 HBM 往返。短序列、小 batch、算力受限的场景,开了也几乎没感觉。永远先 profiling,再谈收益。

记住:性能模型不是用来“显得专业”的,它是你避免盲目优化的刹车。下一节我们把镜头转向另一个常被忽视的维度——数值稳定性,毕竟“快”如果换来“算错”,那优化就是负收益。

3.1.7 把性能模型连回工程决策

这一节的产出,是给你一张“该不该上 FA-2 / PagedAttention”的判断表:(这张判断表与第 2 章 2.3 节“两者如何协同”是一体两面——2.3 讲它们职责怎么切分,本节讲切分之后收益怎么量化。)

3.1.8 实战前的小练习(自己算一遍才记得住)

光看不练容易忘,给你两道“马上能算”的题,建议拿张纸推一遍:

  1. 算显存账:设 d=128、fp16(2 字节)、batch=1,求 n=8192 时,朴素注意力要物化的 S+P 两张矩阵共占多少 MB?把它和第 1 章的 KV Cache 公式对比,你会更清楚“注意力中间矩阵”和“KV Cache”是两类不同的显存压力。
  2. 定性判断:你的服务是“客服问答(平均 200 字对话)”还是“合同审查(一次喂 32K 文档)”?结合本节的判断表,分别给出 FA-2 与 PagedAttention 的优先级建议,并说明为什么。

这两题没有标准答案的“数字”,但推导过程本身就是把 Roofline 和算术强度内化的过程。等第 4 章你面对真实配置时,会发现这些账早就算在心里了。

3.1.9 衔接下一节:快和稳,是同一枚硬币的两面

我们已经把“为什么快”说透了。但很多工程师心里还有一个没说出口的顾虑:“你又是 tiling、又是分块、又是 SRAM 融合,绕了这么多弯,算出来的还是原来那个注意力吗?” 这个顾虑必须被正面回答,否则你永远不敢在生产里真开 FA-2。下一节 3.2 就把镜头转向数值稳定性:我们会证明 PagedAttention 只改排布不改数学,会讲清共享场景的正确性边界,也会给你一套“分页 vs 连续”的一致性验证清单。看完下一节,你既能回答“为什么快”,也能回答“凭什么信”——这两件事,加起来才是工程上真正可用的加速。


作者与出处
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 搬砖请按F5的小龙虾 转发
评论区 (0)
U