周师傅是城南酒楼最有名的掌勺,今晚他接到一单“百料佛跳墙”。他的灶台边有一块小案板,转身就能拿到调料,可惜一次只摆得下几碗料;十几米外的仓储区能装下几百种食材,可每次取货都要推车穿过半个后厨,来回一趟气喘吁吁。案板就是 GPU 里的 SRAM,仓储区就是 HBM(高带宽显存)。周师傅很快发现:一锅菜从备料到出锅,真正下锅翻炒不过十几分钟,大半时间全耗在“搬”上。 标准注意力算法正是那个“爱搬运”的厨师:它算出两个巨大的中间矩阵 S 和 P,用完就塞回仓库,下一步又搬回来。Flash Attention 则完全不同——它把食材切成小块,每次只搬一小批上案板,在案板上顺手完成所有调味(在线 Softmax),中间产物绝不回仓库。数学结果与标准算法分毫不差,但仓库到案板的搬运量少了一个数量级。 这篇文章会带你拆解这套“流水案板”的全套功夫:先看清 HBM 与 SRAM 的层次结构,再算算标准注意力浪费了多少搬运,接着学 Tiling 分块、在线 Softmax、复杂度量化,最后落到工程实现与调优经验。学完你就能理解:为什么大模型训练越来越依赖 Flash Attention 这类 IO 感知算子,以及 GPU 上“算得快”和“跑得快”之间的距离到底有多远。
对 AI 从业者来说,这是一堂性价比极高的性能课:搞懂“内存搬运”这个隐形瓶颈,你就能看懂大模型框架里 80% 的 attention 加速手段,无论是训练长上下文、优化推理延迟还是算子选型,都能一眼看穿底层原理。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
显存层次结构
周师傅的厨房里,最难的不是颠勺,而是“取料”。案板就在手边,转身能抓到葱姜蒜,可一次只摆得下几碗;仓库能装几百种食材,但每次往返都像穿越半个后厨。他掐表算过:一锅菜真正下锅翻炒不过十几分钟,运料却耗掉大半个钟头。所以周师傅立下第一条规矩:能一次拿齐的料,绝不跑第二趟。
GPU 的“两块地”和厨房如出一辙。HBM(High Bandwidth Memory)是显存,容量以 GB 计,A100 上就有 40—80GB,但带宽只有约 2TB/s;SRAM 是片上缓存,紧贴计算单元,每个 SM 只有一百多 KB,却能提供约 19TB/s 的带宽,快了近一个数量级。任何计算都要先把数据从 HBM 搬进 SRAM 才能动手,离计算单元越近,取数越快,地方也越小。
于是决定算子快慢的关键往往不是 FLOPs(每秒浮点运算次数),而是搬运时间:搬运时间 = 数据量 / 带宽。一个 N×N 矩阵要从 HBM 读一遍,耗时就是 N² 个元素除以 2TB/s。像 attention 这种“中间矩阵又多又大”的算子,天然是 memory-bound(受内存带宽限制)——计算单元常常饿着肚子等数据,空转的算力就是被浪费的锅气。
周师傅的结论是:少跑仓库比加快颠勺更值钱。这决定了后面所有策略的方向——不是把菜做得更复杂,而是把“搬运”降到最低。理解了这一点,你就握住了 Flash Attention 的灵魂。
- D(数据量)需要搬运的元素个数或字节数。比如读 Q、K 两个 N×d 矩阵,D=2Nd;而一个 N×N 的中间矩阵,D=N²,N=8192 时高达 6700 万个元素。
- B_b(搬移带宽)单位时间能搬多少数据。HBM 约 2TB/s,SRAM 约 19TB/s,差近一个数量级,这就是“仓库一趟顶案板十趟”。
- T(搬运时间)数据量除以带宽,得到纯粹“在路上”的耗时。带宽不变时,数据量翻倍,耗时就翻倍;反过来,只要把 D 砍掉一个量级,时间就省下一个量级。
标准注意力瓶颈
老办法做佛跳墙是这样的:把几十种食材全部切好、焯好,分装成半成品送回仓库冷藏;要炖的时候,再一盒盒搬回案板。听上去很有条理,问题是一道菜来回要搬四趟——仓库门口排起长队,所有厨师都在等货。周师傅知道,这菜不是做不快,是被“搬运节奏”拖死的。
标准 attention 也这么干。它有三步:先算 S=QKᵀ,得到一个 N×N 的分数矩阵;再对 S 按行做 softmax 得到同样 N×N 的 P;最后算 O=PV。问题是 S 和 P 都是 N×N 的“半成品”。GPU 的 SRAM 根本装不下整个 N×N 矩阵(N=8192 时 S 有 6700 万个数),所以只能写回 HBM,下一步再读回来——半成品在仓库和案板之间反复折腾。
细数这笔账:S 写回一次、读回一次,P 写回一次、读回一次,光是这两个矩阵就产生 4N² 次元素搬运;再加上 Q、K、V、O 各一趟 Nd,总计约 4N²+4Nd。N 从 1K 涨到 8K,搬运量暴涨 64 倍。而 GPU 的算力余量远大于带宽余量,于是“数据在路上”的时间彻底盖过“数据在计算”的时间,SM 的算力大片大片刻在等数据。
周师傅一看账本:上菜太慢不是因为锅小,而是因为半成品在仓库和案板之间反复折腾。好,那就立新规矩——半成品一律不许回仓库。这就是 Flash Attention 的起点:让 S 和 P 永远不出案板。
- S 写回 HBM算完 S=QKᵀ 后,N×N 的 S 无法留在 SRAM,必须先存到显存。
- S 读回算 softmaxsoftmax 要按行处理 S,又把它从 HBM 读回来,同时把结果 P 写回显存。
- P 再读回算 PV最后一步 O=PV 要从 HBM 读回 P 才能和 V 相乘。
- Q、K、V、O 各一趟这四个 N×d 矩阵各读/写一次,贡献 4Nd,在 N 很大时可以忽略。
分块Tiling策略
新规矩立下后,周师傅换了个思路:既然案板只放得下几碗料,那就把整锅菜拆成上百批,每批刚好摆满案板;切一批、炖一批、装一批,绝不让任何半成品离开案板。这样做菜慢了吗?不,反而快了——因为没人再整天推着小车往返仓库,所有人的时间都花在真正做菜上。
Flash Attention 的分块 Tiling 正是如此:把 Q、K、V 按行切成若干块,每次只取一个 Q 块和若干 K、V 块进 SRAM,在片上完成小块的 QKᵀ、softmax、PV,再更新输出 O 的对应行块。S、P 这两个 N×N 矩阵从头到尾只存在于 SRAM 里,压根不会出现在 HBM 中——半成品不出案板。
块大小怎么定?SRAM 里同时要放四样东西:Q 块、K 块、V 块、O 块,每块形状是 B×d,四份加起来 4Bd 个元素,不能超过 SRAM 容量 M。于是得到经典结论 B=M/(4d)。外层循环遍历 Q 的行块,内层循环遍历 K、V 的列块;内层每算完一块,就把这一批的“味道贡献”累加到 O 上,等外层全部跑完,O 就是完整的注意力输出。
周师傅把这套流程叫作“流水案板”——案板永远是满的,仓库永远是被冷落的。唯一的问题是:分批调味,怎么保证最后拼出来的味道和一次性下锅一模一样?这就轮到在线 Softmax 登场了。
- M(SRAM 容量)A100 上每个 SM 的 SRAM 约 192KB,以 fp16 计算大约能装 96000 个元素。
- 四块矩阵瓜分 M案板上要同时摆 Q 块、K 块、V 块、O 块,每块 B×d,总占用 4Bd 不能超限。
- 解出块大小不等式两边同时除以 4d,得到块大小的上限,实际取整为向上取整。
在线Softmax算法
难题来了。佛跳墙的汤汁讲究“整体平衡”:要先知道整锅最咸的底味,才能决定每味调料的比例。可周师傅一次只炖一批,怎么知道后面批次的咸淡?他的办法是在围裙口袋里揣一本小本子,记两个数字:见过的最咸的一勺(m),以及当前所有调料的比例累计(l)。每批新汤端上案板,先尝一口:若更咸,就把本子上旧的比例整体打个折扣,再混入新批次的贡献。
这正是在线 Softmax 的核心。行 softmax 需要全行的最大值和指数和,但分块后每块只有局部最大值。算法的巧妙之处在于:维护“运行中的”统计量(m 是见过的最大的分数,l 是指数归一和),每处理一个新块做一次合并更新,输出 O 也随之重缩放——小本子越记越厚,但永远只需要记两笔。
具体来说,假设已处理若干块,当前统计量是 (m, l, Õ)。新块分数 S_ij 的局部最大值为 m_ij:先比大小得到 m_new;旧输出和旧统计都建立在旧最大值 m 上,需要乘以折扣 r=e^{m-m_new}(若新最大值更大,折扣小于 1,相当于把整锅味道按新基准“兑淡”);再累加新块的指数贡献与加权 V,最后统一除以 l_new 得到精确的 softmax 输出。整个过程数学上与标准 softmax 完全等价,同时天然继承了“减最大值防溢出”的数值稳定性技巧。
周师傅的小本子越记越顺:见过最咸的一勺,记下来;总比例,记下来。最后出锅时哪怕分了几百批,勾兑出来的汤汁与一次猛火炖出的味道分毫不差。分批没有牺牲味道,只是省掉了搬运。
- 比大小得到新基准 m_new本块的局部最大值和运行中的最大值比大小,大者担任新的行最大值,保证后续指数运算不会溢出。
- 折扣因子 r旧统计量建立在旧最大值 m 上,换了新基准后要整体乘以 r=e^{m-m_new};若新最大值更大,r 小于 1,相当于把旧汤汁按新咸度“兑淡”。
- 更新指数归一和 l旧和乘上折扣,加上新块所有分数的指数贡献,得到合并后的分母。
- 重缩放输出累加器 Õ未归一化的输出同样先乘折扣,再叠加新块的加权和(softmax 分数乘 V 向量)。
- 归一化出锅全部块处理完后,把累加器除以 l_new,得到与标准 softmax 逐元素一致的最终输出。
IO复杂度量化
光说“少跑仓库”不够,周师傅有本账:老办法一道菜在仓库和案板之间来回折腾,新办法案板流水作业,总搬运量到底省了多少?他专门把每次搬运的件数记下来,算了三天三夜。账算明白了,才知道这新流程值不值得铺开。
Flash Attention 论文也算了这笔账。标准注意力搬运量是 4N²+4Nd,与 N² 成正比,N 每翻一倍流量涨四倍,这是 attention 在大模型训练中越来越吃时间的原因。Flash Attention 的搬运量则取决于 SRAM 容量 M:块大小 B=M/(4d),内层循环要遍历 N/B 轮,每一轮 K 和 V 各被读一块,所以 K、V 各被重复读取 N/B 次。
算下来,Flash Attention 的 HBM 访问量约 8N²d²/M(外加读一次 Q 和写一次 O 的 2Nd,可忽略)。两者之比约 M/(2d²)。以 A100 为例:每 SM 的 SRAM 约 96000 个 fp16 元素,取 d=64,则 M/(2d²)=96000/8192≈11.7——HBM 流量直接少一个数量级。注意这里只省“搬运”,计算量一分没少,Flash Attention 是精确算法,不是近似算法。
周师傅把账本一拍:省下的不是调味料,而是搬运工的工钱。案板越大(M 越大)、一批能放的料越多,省得越多;头维度 d 越大,一批能放的“行”越少,折扣就小些。这笔账清清楚楚——少搬一个数量级,速度自然上一个台阶。
- 内层循环轮数 T每个 Q 块要遍历 K、V 的所有列块,轮数等于 N/B,代入 B=M/(4d) 得 4Nd/M。
- K、V 被反复读取每一轮都要读 K、V 各一块,总共读 2Nd·T 个元素。
- 与标准流量作比标准的 4N² 除以 Flash 的 8N²d²/M,化简得到 M/(2d²)。
- 代入典型数值A100 上 M≈96000(fp16 元素)、d=64,加速比约 11.7 倍。
工程实现细节
想把流水案板真正落地,光有想法不够。周师傅把三大工序——切配、焯水、下锅——合成同一个灶台流程,中间不再换人、换车、换库房;灶台上炖着的同时,徒弟们已在备下一批料,这叫“边算边搬”。后厨的动线彻底重组,半成品永远不落地。
工程上对应三件事。第一是 Kernel 融合:传统方案要启动多个 kernel(QKᵀ、softmax、PV),每个 kernel 都要从 HBM 读中间结果;Flash Attention 把三步写进同一个 CUDA kernel,一次启动、全程在 SRAM 内完成。第二是反向传播优化:标准反向需要 S、P 这两个 N×N 矩阵,Flash Attention 不存它们,而是从已保存的输出统计量 l 和 O 现场重计算,用额外计算换掉 N² 量级的显存。第三是并行度设计:每个 head 独立计算,batch×head 的并行度天然很高,多头之间互不干扰。
由此带来的显存收益是质的飞跃:前向不再需要为 S、P 申请 N×N 的显存块。标准注意力显存占用 O(N²),Flash Attention 降到 O(N)——只有 Q、K、V、O 和每行的统计量 m、l。论文报告在 GPT-2 训练上端到端提速约 15%,注意力算子本身快约 3 倍;序列越长、头越多,省下的显存越可观。
周师傅的灶台改造完成:一个灶眼从头做到尾,中间不落地;徒弟流水线备料,灶火不停。仓库空了,锅气足了。显存不再是长序列的天花板,算力才真正花在了刀刃上。
- S、P 是显存大户标准算法要为两个 N×N 矩阵各开一块显存,N 稍大的中型模型就会吃进数 GB。
- Flash 只留输出与统计量S、P 不落 HBM,显存只剩 Q、K、V、O 和每行的 m、l。
- 量级对比N 很大时 4Nd 远小于 2N²,所以一个是 O(N²),一个是 O(N)。
性能调优经验
新流程跑通了,周师傅没闲着:案板如果大了一圈,每批就能多切几刀;菜场送货的车多了,他调整批次让案板永远不空。他把这套“按硬件调批次”的经验记成厨艺手册,谁家灶台什么尺寸,一看便知怎么配菜。
调优的核心是“匹配硬件尺寸”。SRAM 越大,B=M/(4d) 越大,内层循环轮数越少,K、V 被重读的次数越少——H100 的 SRAM 更大、HBM 带宽翻倍,Flash Attention 的收益自然更明显。序列越长,N² 项越突出,省流量的优势越放大,这正是长上下文模型把 FlashAttention 当作标配的原因:8K、32K 甚至 128K 上下文,没有一个能离开它。
实践中的调优点包括:块大小不是越大越好,过大会挤占 SRAM 导致线程占用率下降;kernel 内部要组织共享内存的读写避免 bank conflict;用双缓冲把 HBM 搬运与 SRAM 计算重叠,让“搬运”和“计算”并行进行;反向传播时 m、l 的保存可以压缩存储。FlashAttention-2 进一步改进了线程块并行策略,让长序列上的吞吐再上一个台阶;配合 MQA/GQA 等变体减少 KV 读取,推理场景还能再省一笔带宽。
周师傅的经验是:算法是骨架,硬件是灶台,调优就是按灶台的火力来配批次。知道瓶颈在“搬”不在“算”,你的每一分调优力气都会花在刀刃上——这也是 Flash Attention 系列算子给整个 AI 工程界上的一课。
AI 应用场景
大模型长上下文训练加速
阶段:模型训练
解决的问题:标准 attention 的 HBM 流量是 O(N²),序列从 1K 拉到 8K 时显存与带宽双双告急,训练几乎被搬运拖垮。Flash Attention 用 Tiling 加在线 Softmax 把中间矩阵留在 SRAM,流量少一个数量级,长序列才跑得动。周师傅的道理:半成品不出案板,仓库就不再是瓶颈。
具体案例:在 GPT-2 中等规模训练中,把 attention 替换为 FlashAttention kernel,论文实测端到端训练提速约 15%,注意力算子本身快约 3 倍;当上下文从 1K 扩展到 8K 时,显存占用依然平稳,训练不必再频繁做序列截断。
推理服务降本增效
阶段:推理部署
解决的问题:自回归解码每个 token 都要读取全部 KV cache,推理延迟被 HBM 带宽卡死。减少 KV 读取次数与搬运量,直接决定单卡吞吐。周师傅的小本子哲学在这里变成:能少搬一趟就少搬一趟,延迟立刻降下来。
具体案例:在推理引擎(如 vLLM、TGI)中把 attention kernel 替换为 FlashAttention 实现,7B 级别模型的单卡并发数可提升 20%—50%,首 token 延迟明显下降;配合 MQA/GQA 减小 KV cache 体积,带宽压力进一步缓解。
超长文档问答服务
阶段:应用服务 / 数据接入
解决的问题:十万 token 的合同、论文要做摘要与问答,标准 attention 的显存 O(N²) 直接爆显存;Flash Attention 的显存 O(N),消费级显卡也能处理超长上下文,不再需要把文档暴力切段导致语义断裂。
具体案例:在 24GB 显存的单卡上,用内置 FlashAttention 的推理框架加载 32K—128K 上下文模型,对整份年报或论文直接提问,文档无需预切分,回答质量显著优于分段检索方案。
Python 演示
import numpy as np def softmax(x): m = x.max(axis=-1, keepdims=True) e = np.exp(x - m) return e / e.sum(axis=-1, keepdims=True) def standard_attention(Q, K, V): S = Q @ K.T P = softmax(S) O = P @ V return O def flash_attention(Q, K, V, B=2): N, d = Q.shape O = np.zeros((N, d)) # 未归一化输出累加器 m = np.full(N, -np.inf) # 每行运行最大值 l = np.zeros(N) # 每行运行指数和 for i in range(0, N, B): Qi = Q[i:i + B] for j in range(0, N, B): Kj = K[j:j + B] Vj = V[j:j + B] Sij = Qi @ Kj.T m_ij = Sij.max(axis=1) new_m = np.maximum(m[i:i + B], m_ij) r = np.exp(m[i:i + B] - new_m) pij = np.exp(Sij - new_m[:, None]) l_ij = pij.sum(axis=1) O[i:i + B] = O[i:i + B] * r[:, None] + pij @ Vj l[i:i + B] = l[i:i + B] * r + l_ij m[i:i + B] = new_m O[i:i + B] = O[i:i + B] / l[i:i + B, None] return O if __name__ == "__main__": np.random.seed(0) N, d = 4, 3 Q = np.random.randn(N, d) K = np.random.randn(N, d) V = np.random.randn(N, d) O1 = standard_attention(Q, K, V) O2 = flash_attention(Q, K, V, B=2) err = np.abs(O1 - O2).max() print("max error:", err) assert err < 1e-10, "flash attention is not equivalent!" print("flash attention equals standard attention")
m = np.full(N, -np.inf)每行维护一个“见过的最咸分数”,初始负无穷保证第一块直接接管。new_m = np.maximum(m[i:i+B], m_ij)新老最大值比大小,谁大谁当新的行最大值 m。r = np.exp(m[i:i+B] - new_m)重缩放折扣:旧统计建立在旧最大值上,换基准要打这个折扣。O[i:i+B] = O[i:i+B] * r[:, None] + pij @ Vj旧输出按折扣重缩放后,叠加新块的 P·V 贡献。l[i:i+B] = l[i:i+B] * r + l_ij指数归一和同步更新,这是在线 softmax 的“勾兑比例”。O[i:i+B] / l[i:i+B, None]全部块算完后统一归一,得到与标准 softmax 一致的输出。
常见误区
误区名字带 Flash,估计是用随机采样或稀疏化来近似注意力吧?不然怎么会快那么多?
正解它不是近似方法。Flash Attention 的计算量、参与的位置、softmax 的分数一个都不少,只是重排了执行顺序:分块后让中间矩阵 S、P 只留在 SRAM,不再写回 HBM。数学上与标准 softmax 逐元素等价,端到端精度无损失。就好比周师傅把佛跳墙分几十批炖,料一点没少,只是省掉了来回仓库的搬运。
为何常见:Flash 一词容易让人联想到之前的稀疏/近似注意力(如 Longformer、Linformer),加上论文主打“快”,读者先入为主地脑补成近似。
误区我这显卡显存几十 GB,中间矩阵写回显存有什么大不了的?容量够用就行。
正解瓶颈是带宽,不是容量。写一次 N×N 的 S 矩阵虽然“放得下”,但要把 HBM 带宽占满好几毫秒,而计算单元在几微秒内就把数据“饿死了”。算得快、等得久,正是 memory-bound 算子的典型症状。周师傅的仓库再大,运一趟要半个钟头,菜就凉了。
为何常见:人们习惯用容量衡量“够不够”,GPU 宣传页上最显眼的也是显存大小,带宽这个隐性指标常被忽略。
误区既然分块是精髓,那把块设得越大,一次处理得越多,不是越快吗?
正解块大小被 SRAM 容量硬约束:B=M/(4d),因为 Q、K、V、O 四块要同时驻留。超过 M 就会溢出到 HBM,搬移反而变多;块太小则 K、V 重读轮次 T=N/B 变大,HBM 流量上升。真实调优是在“正好塞满 SRAM”附近找最优,而不是无限增大。周师傅的案板就那么大,硬塞只会把料挤到地上。
为何常见:矩阵乘法中块越大缓存利用率越高是常见经验,容易类比过头;没注意到 SRAM 是稀缺资源,四份矩阵要抢同一块地方。
误区在线 softmax 是增量更新的,结果肯定和一次性算的 softmax 不一样,是不是牺牲了精度?
正解它在数学上等价于标准 softmax。维护的 m(运行最大值)和 l(指数和)经过合并更新后,与直接对整个行算出的最大值、和完全一致;唯一差别是浮点累加顺序,误差约 1e-6 量级,而且它还继承了“减最大值”的数值稳定性技巧。论文实验确认端到端精度无损失。
为何常见:“在线/增量”在不同领域常代表近似(如在线学习、随机梯度),读者按惯性理解;加上看不见完整的 P 矩阵,心里不踏实。
面试题
Q1. Flash Attention 加速的核心手段是什么?
- A.减少矩阵乘法的计算量
- B.减少 HBM 与 SRAM 间的搬运← 正确答案
- C.用近似分数替代精确分数
- D.降低 softmax 的数值精度
答案:B。Flash Attention 的计算量和标准注意力完全一样,它省的是“搬运”:S、P 不再写回 HBM。周师傅的道理——菜的做法没变,变的是不再把半成品送回仓库。C、D 都是近似或降精度思路,与 Flash Attention 的精确性相悖。
Q2. 关于 GPU 中 HBM 与 SRAM 的说法,正确的是?
- A.HBM 容量大但带宽较低← 正确答案
- B.HBM 容量小但带宽很高
- C.SRAM 容量大且带宽很高
- D.SRAM 容量大但带宽较低
答案:A。HBM 是“大仓库”,几十 GB 容量、约 2TB/s 带宽;SRAM 是“小案板”,每 SM 一百多 KB、约 19TB/s 带宽。B、C、D 都颠倒了容量与带宽的关系。记住:容量看 HBM,速度看 SRAM。
Q3. 标准注意力中反复往返 HBM 的中间矩阵是?
- A.Q 和 K 两个输入矩阵
- B.V 和 O 两个输出矩阵
- C.S 和 P 两个 N×N 矩阵← 正确答案
- D.只有一个 Q 矩阵
答案:C。标准注意力把 S=QK^T 和 P=softmax(S) 这两个 N×N 矩阵写回 HBM,下一步又读回,共 4N² 次搬运。Q、K、V、O 各只有一趟 Nd,不是主要矛盾。C 才是“来回折腾”的元凶。
Q4. Flash Attention 用到的关键技术包括?
- A.分块 Tiling 把计算装入 SRAM← 正确答案
- B.在线 Softmax 合并行统计量← 正确答案
- C.随机掩码采样部分注意力
- D.Kernel 融合避免中间写回← 正确答案
答案:ABD。A、B、D 正是 Flash Attention 的三大支柱。C 是近似注意力(如 BigBird)的思路,Flash Attention 不采样、不掩码,每个位置都精确计算,只是重排了计算顺序。
Q5. 在线 Softmax 中的符号 m 记录的是什么?
- A.当前行已见过的最大分数← 正确答案
- B.当前块的分数平均值
- C.整个矩阵的分数之和
- D.输出向量的模长平方
答案:A。m 是“见过的最咸一勺”——运行中的行最大值。新块局部最大值 m_ij 与它比大小,决定是否需要对旧输出打折扣重缩放。B、C、D 都不是 m 的含义;在线 softmax 的 m 只负责数值稳定性与重缩放基准。
Q6. 块大小公式 B=M/(4d) 中数字 4 表示?
- A.每份数据要复制四份拷贝
- B.SRAM 同时放 Q、K、V、O 四块← 正确答案
- C.整个矩阵被切成四块处理
- D.浮点数恰好占四个字节
答案:B。SRAM 里要同时驻留 Q 块、K 块、V 块和输出 O 块,每块 B×d,总元素 4Bd 不能超过 M,所以 B=M/(4d)。这是“案板刚够摆四碗料”的数学表达。A、C、D 都是想当然的猜测。
Q7. Flash Attention 中 K、V 被重复读取的轮次 T 是?
- A.T=N/B,SRAM 越大轮次越少← 正确答案
- B.T=N/B,SRAM 越大轮次越多
- C.T=N/B,轮次与 SRAM 无关
- D.T=d/B,与序列长度无关
答案:A。T=N/B=4Nd/M。B 越大每轮处理的 K 块越大,总轮数越少,K、V 重读次数越少,HBM 流量越低。这解释了为什么 SRAM 越大 Flash Attention 收益越大,也支撑了加速比 M/(2d²)。
Q8. 关于 Flash Attention 的 HBM 流量,正确的有?
- A.标准注意力量级是 O(N²)← 正确答案
- B.Flash 流量约 O(N²d²/M)← 正确答案
- C.典型配置下少一个量级← 正确答案
- D.Flash 的 FLOPs 也减半了
答案:ABC。A、B 是论文比较的两个复杂度;C 对应加速比 M/(2d²)≈10 倍的结果。D 错误:Flash Attention 不省任何计算,FLOPs 与标准相同,它只省 HBM 搬运。
Q9. Flash Attention 的结果与标准注意力的关系是?
- A.精确等价,仅浮点舍入差异← 正确答案
- B.有损近似,误差完全不可控
- C.与标准的结果完全不同
- D.只在短序列时近似成立
答案:A。在线 softmax 维护的 m、l 与一次算出 softmax 的统计量数学上一致,输出逐元素等价,只是浮点运算顺序不同带来约 1e-6 量级的舍入误差。B、C、D 都把它误解成了近似方法。
Q10. 已知 M=100K 元素、d=100,Flash 相比标准的 HBM 流量加速比约为?
- A.约 1 倍,流量完全没有减少
- B.约 5 倍,与 M/(2d²) 估算吻合← 正确答案
- C.约 10 倍,对应加速比 d²/M
- D.约 1000 倍,因为访问归零
答案:B。M/(2d²)=100000/(2×100²)=5,所以选 B。C 把公式记反了(d²/M 远小于 1);A 忽略了两者常数差异;D 错误,Flash 仍有 Q/K/V 搬入和 O 搬出,HBM 访问不会归零。周师傅会说:仓库省了九成人力,但不是零人力。