读者读完本章,应该能回答一句:为什么 FlashAttention-2 的加速在长序列上更夸张、PagedAttention 共享显存后结果还准不准,以及——当别人说“我开了 FlashAttention 但没快多少”时,你该用什么框架去拆穿或证实。
第 1 章我们建立了“注意力为什么慢、为什么费显存”的直觉;第 2 章我们把 FlashAttention-2(算子层)和 PagedAttention(系统层)两个模块的实现拆开了看。这一章要补上最容易被跳过的两块拼图:性能模型与数值稳定性。它们看起来“偏理论”,但恰恰是你在真实排障、写技术评审、向上汇报“要不要上这套优化”时,真正用得上的武器。
很多工程师把 FlashAttention 当成黑盒,一句 attn_implementation="flash_attention_2" 就完事。这没问题——直到某天你发现:换了更强的卡没快多少、长上下文收益不及预期、或者对整齐输出和原来对不齐,于是完全无从下手。本章的目的,就是让你在那种时刻有路可走。
在进入推导前,先把这一章要回答的问题摆清楚,避免你读的时候“看个热闹”:
这三个问题,分别对应 3.1(性能模型)和 3.2(数值稳定性与共享边界)。它们之间不是割裂的:性能模型告诉你“该往哪优化”,数值稳定性告诉你“优化后还能不能信”,二者共同构成你做工程权衡的底层依据。
本章反复出现一个判断框架,建议你在脑子里先钉死它:
先判断你卡在“带宽”还是“算力”,再决定用哪个优化。绝大多数 LLM 推理场景,卡的是显存带宽,不是乘法器。
为什么这条重要?因为如果你的问题是“算力受限”(比如 batch 太小、并行度没拉起来),那换 FlashAttention、上 PagedAttention 都救不了你——你该去调批大小、数据并行。反之,如果 profiling 显示 HBM 带宽被打满、SM 算力闲着,那本章讲的两条路线(减少 HBM 往返、压缩 KV 显存)才是正解。这一章的方法论,本质上就是教你把“感觉慢”翻译成“具体卡在哪、该动哪根线”。
读完本章,建议你把下面两件东西存进自己的工具箱:
这两件东西看起来朴素,却是区分“会跑 demo”和“能扛生产”的分水岭。我带新人时,常要求他们把 Roofline 小抄贴在显示器边——不是为背公式,而是养成“碰到慢,先问卡在带宽还是算力”的肌肉记忆。等你形成这种直觉,很多“玄学性能问题”在你眼里会变成一目了然的账本。
我见过太多团队在推理优化上“交学费”,根子几乎都在这里——只学了“怎么做”,没学“为什么”和“怎么验证”。举三个真实场景:
这三件事,本章都给你“防坑地图”。所以请别把这一章当理论附录略过——它是你从“调包侠”升级为“能负责的人”的关键一跃。
为了让你脑子里有张地图,我把三章的关系再钉一遍:
attn_implementation 怎么选、量化怎么配。那是“整车交付手册”。没有第 3 章,第 4 章的参数你只会照抄、不会改;没有第 4 章,第 3 章的方法论你只能纸上谈兵。三章串起来,才是一次完整的“懂原理 → 会验证 → 能落地”。
这一章不引入新模块,而是给你“看懂前两章 + 落地后两章”的眼睛。3.1 用 Roofline 与算术强度,把“FA-2 为什么快、为什么长序列更赚”变成可量化的账本;3.2 则把注意力聚焦到 PagedAttention 的共享语义与数值等价性,给你一套上线前的正确性验证方法。
如果你是从第 1 章顺着读下来的,这里顺便把前后文的勾连点一下:第 1 章 1.1 节我们算过“S+P 两张中间矩阵随 n² 膨胀”,那正是本节 Roofline 里“朴素注意力落在带宽斜坡”的微观来源;第 2 章 2.2 节讲的块表与共享,正好是 3.2 节“共享正确性边界”的铺垫;而第 2 章 2.3 节所讲的 FA-2 与 PagedAttention 协同分工,也正需要本章的数值不变量来兜底——协同一旦缺少统一的归一化基准,就可能悄悄引入误差。所以本章不是空中楼阁,它是把前面埋的线头收拢成网。
如果把整本教程当成一次“从使用者到负责人”的升级,第 1、2 章让你“会用”,第 3 章让你“敢负责”——因为你知道加速从哪来、知道结果是否可信、知道出问题去哪查。这种底气,比背下任何一组参数都值钱。
读懂这两节,你再去看第 4 章的 vLLM / HuggingFace 配置,就不会只是“照抄参数”,而是能解释每个参数背后的取舍:块大小为什么常常取 16,fp32 累加为什么默认开启,并行采样为什么能省下那么多显存——这些问题的答案,都埋在 3.1 和 3.2 里。