专题研修

06|推理服务的真实瓶颈:内存、FlashAttention、分页与调度

专题研修约 3.7 千字1 组分步图解

目标:从张量尺寸推导服务成本,知道一次优化减少的是计算、内存搬运、碎片还是排队;能够避免用CPU恒等式实验冒充GPU性能结果。

本章目录

沿着对象与状态理解本章

服务优化要先定位搬运、重复计算、碎片和调度各自的占比,再选择技术。

下方图解的固定输入在“输入与适用条件”中声明。它用于解释本章机制,不与本章其他独立例子的数值暗中接续。

动态图解 · O04

FlashAttention:一边读一边累计,不攒整张表

不把完整注意力表存下来,怎样仍算出同一输出?

想象分批称重汇总:每批到来时更新“最大刻度、总重量、内容加权和”,不用把所有中间单据再写一遍显存。最大刻度变化时,旧累计必须跟着换刻度。这个在线归一化过程解释了省读写如何与同一数学结果兼容。

m截至当前分块的最大分数。
l按当前最大值缩放后的指数总和。
加权累计尚未除以l的Value贡献和。

输入与适用条件:独立单查询例:读取顺序C/A/B,分数[0,2,1],对应V为[[5,5],[10,0],[0,20]]。为展示最大值变化而设,不接用F09候选顺序。

1 / 5 · 普通写法先想象整张分数表

第1步,共5步

窄屏可左右滑动图形,或点击“放大图形”。文字解释紧随图后。

FlashAttention:一边读一边累计,不攒整张表:普通写法先想象整张分数表示意:多查询 × 多Key 的分数表s00s01s02s03s04s05s10s11s12s13s14s15s20s21s22s23s24s25s30s31s32s33s34s35后面缩为“一个查询、三个候选”的可复算在线归一化例子。

在长序列中,把所有查询对所有Key的分数完整存下来会产生很大的中间表。FlashAttention改变分块与读写组织,目标不是随意丢弃低分位置。

本步状态由图形与说明共同给出。

默认静止。用“下一步”看完解释再继续;播放到最后一步自动停止。键盘聚焦播放器后,可用左右键逐步查看、空格播放/暂停。图中颜色辅助区分,含义同时用文字注明。

为什么需要

大中间矩阵造成显存读写与容量压力。

怎样实现

分块计算并以在线softmax维护归一化统计,减少外部显存访问。

可能的代价与误解

实现复杂;数值顺序变化有舍入差异;不适用的硬件或形状收益可能很小。

如何判断是否做对

与完整softmax加权结果做容差对照,再在目标硬件实测而非把教学计数当加速倍数。

1. Prefill与Decode的资源画像

Prefill处理整个输入前缀,矩阵运算通常具有更高并行度;Decode每步只新增少量位置,却需要读取模型权重和增长的KV。具体瓶颈取决于batch、模型、精度与硬件,不能绝对说前者总是算力受限、后者总是带宽受限。它们是常见分析方向,不是无需测量的结论。[N11]

以注意力为例,完整前缀长度T的分数矩阵规模为T²;标准全注意力的计算随T²增长。缓存解码时一个新位置对历史T个键评分,单步该部分约随T增长,整个长序列累积仍有相应代价。把KV缓存理解成“以后不需要处理历史”是错误的:省掉的是旧位置K/V重算,不是读取历史注意力所需的数据。

2. Roofline思考:算力还是数据移动

设一次操作需要F个浮点运算,搬运M字节,设备峰值算力P和带宽W。粗略下界可写为时间≥max(F/P,M/W),实际还有启动、同步、通信、调度和利用率损失。算术强度F/M帮助判断优化方向。

例如减少中间矩阵写回能改善内存受限部分,即使数学运算次数略增加,仍可能更快。反过来,对已经算力饱和的部分,增加重新计算可能变慢。不能只凭FLOPs数量或GPU利用率一个数字判断服务瓶颈;需结合内存带宽、算子时间、队列和请求分布。

3. FlashAttention为什么能不保存完整注意力矩阵

普通实现可能把S=QKᵀ/√d、softmax概率等T×T矩阵写入高带宽内存。分块算法在更近的片上存储中处理块,并维护归一化统计,使结果不必依赖完整矩阵同时存在。FlashAttention针对这种IO问题组织精确注意力计算,而不是把全注意力变成线性注意力。[N10]

对于一个查询行,已处理分数的最大值m、指数和l、未归一化加权和a为:l=Σexp(s−m),a=Σexp(s−m)v。看到新块S、V时:

m' = max(m, max(S))
l' = exp(m−m') l + Σ exp(S−m')
a' = exp(m−m') a + Σ exp(S−m') V
最终输出 O = a/l

为什么需要重缩放旧统计?新块最大值更大时,旧l和a是相对于旧m计算的,必须转成相对于m'的尺度。只更新m而不重缩放,会给不同块错误权重,结果随分块方式变化。这是值得故意注入的错误。

本书online_attention实现上述恒等式,并与普通softmax注意力比较不同块大小。它没有CUDA核、共享内存布局、反向算子或硬件性能测量。反向中可利用保存的统计重算部分概率,换取不保存完整矩阵的空间收益;生产实现还必须处理mask、dropout、数值类型和批量布局。

4. 分页KV缓存解决的是分配与共享

长请求长度不一,若每条请求预留连续最大KV空间,容易造成浪费与碎片。PagedAttention把逻辑Token位置映射到固定大小的KV块,物理块可以非连续;共享前缀可引用共享块,分叉写入时需要合适的共享/复制规则。[N11]

块太小,元数据、寻址与管理成本上升;块太大,最后一个块的内部碎片增大。缓存压缩与量化是另外的技术,分页本身并不自动减少每个有效Token的K/V数值字节数。也不能因为底层共享物理前缀,就忽略租户隔离或缓存侧信道。

服务调度必须知道多少KV容量可以分配。允许过多长请求同时进入,可能导致抢占、换出或失败;单看RPM限额无法反映这种压力。可以分别限制在途Token、请求数、输出上限,并在调度中考虑服务质量目标。

5. Continuous Batching与公平性

静态batch等一组请求一起完成,新请求不能及时加入;连续批处理在迭代边界加入或移除请求,提高设备利用率。但一个长prefill可能阻塞已经在decode的短请求,影响逐Token延迟。将prefill分块、分离不同阶段或设计公平调度,都有额外复杂度和硬件条件。

指标要分开:TTFT看首次响应,TPOT看输出Token间隔,端到端时间看用户任务,多租户还要看尾延迟。为了吞吐提高batch,可能牺牲交互体验;为了最低延迟,每次只跑一条,又可能降低资源利用率。所谓最优只能针对负载与SLO定义。

Little定律在稳定系统中给出在途量L=到达率λ×平均逗留时间W。它不描述具体队列尾部分布,却能帮助检查容量规划是否自洽。接近饱和后延迟非线性上升,不能用低负载单请求基准直接预测生产峰值。

6. Prompt缓存与KV缓存不要混为一个开关

模型内部KV缓存是推理状态;服务的前缀缓存可能复用跨请求前缀计算;计费层对缓存命中的定义又是产品契约。应用应稳定可复用的前缀,避免无关时间戳插入开头,但不能为缓存而继续携带已经错误或越权的内容。安全、正确性优先于命中率。[N01][N14]

如果为了压缩删除中间历史,后续前缀可能变化,降低可复用部分。应比较剩余任务的总成本,而不只是这次压缩后输入少了多少。第12章给出压缩盈亏的计算方法。

7. 一份可信的性能实验应该包含什么

先保存模型版本、精度、硬件、服务配置、输入/输出长度分布、并发与warm-up方式。分别测无缓存/有缓存、短/长前缀、单请求/生产并发。输出p50/p95等延迟、吞吐、失败率、显存峰值和任务质量,不用一个最佳单点掩盖尾部问题。

验收题:NumPy分块注意力与普通注意力误差很小,能否认定FlashAttention优化完成?不能。它只验证数学子问题;GPU的布局、同步、实际IO和反向正确性仍待实现。将一种机制的正确性与某一生产系统的性能收益分开,是资深工程学习的底线。

运行示例 · S06

roofline估算为什么只能给下界,不能直接当实测

输入与条件。假想算子需1GFLOP和100MB十进制数据移动;设备峰值100TFLOP/s、带宽1TB/s。

步骤与对象内部动作中间结果 / 新状态
1计算下界10^9/10^1410微秒。
2搬运下界10^8/10^12100微秒。
3理想重叠至少max(10,100)100微秒,而非保证110或100实测。
4实际损失利用率、kernel启动、同步、缓存命中都可能变化实际可以更慢,实际HBM流量也需正确测量。
5优化方向若确为带宽瓶颈降低读取或提高重用可能比单纯增加乘法吞吐更有用。

把过程连起来。性能模型帮助判断瓶颈方向,不能把纸面峰值替代运行测量。

边界与反例。单位采用MB=10^6、TB=10^12;不是任何实际GPU的规格或性能承诺。

依据与适用范围:[FLASH]。示例输入和场景由本书明确设定。

记录保存在本机浏览器。

输入关键词即可检索。

↑ ↓ 选择 Enter 打开Esc 关闭 · 仅本地搜索

阅读设置

阅读设置仅保存在本机浏览器,不上传任何数据。