Skip to content
kefan.life
Go back

Roofline 分析:瓶颈的判定与局限

LLM 推理中,给定模型和硬件,理论上最快能跑多快?Roofline 模型是回答这个问题最简洁的分析框架:用两个硬件参数和一个比值,就能判断计算任务的性能瓶颈在哪。

这篇文章先介绍 Roofline 的基本原理,再回顾一次把它用于资源预估的尝试:为什么单阶段压测可以拟合,总工作量也没有算错,最后仍然低估了混部成本。

Roofline 如何判断瓶颈

任何计算任务在硬件上执行,受两个基本约束1

  1. 算力(Math):芯片每秒能完成多少浮点运算(Peak FLOPs/s)
  2. 带宽(Bandwidth):HBM 每秒能搬运多少字节(Bytes/s)

运算需要算力来做数学计算,同时需要带宽来搬运数据。两者各自的耗时:

Tmath=FLOPsPeak FLOPs/s,Tcomms=BytesBandwidthT_{\text{math}} = \frac{\text{FLOPs}}{\text{Peak FLOPs/s}}, \quad T_{\text{comms}} = \frac{\text{Bytes}}{\text{Bandwidth}}

如果计算和访存能理想地重叠,Roofline 给出的时间下界是:

Tlower=max(Tmath,Tcomms)T_{\text{lower}} = \max(T_{\text{math}}, T_{\text{comms}})

如果两者完全串行,已建模部分的耗时是:

Tserial=Tmath+TcommsT_{\text{serial}} = T_{\text{math}} + T_{\text{comms}}

TserialT_{\text{serial}} 最多是 TlowerT_{\text{lower}} 的两倍,但这个两倍只描述「完全重叠」与「完全串行」两个极端的差异。真实执行还包含 kernel 效率、同步和调度等开销,实际时间可以超过 TserialT_{\text{serial}}。Roofline 描述的是硬件资源约束下的理论下界,不是对真实执行时间的上下界承诺。

算术强度与瓶颈判定

为了快速判断瓶颈在哪一侧,定义算术强度(Arithmetic Intensity),即每搬运一个字节需要做多少次运算:

Ialgo=FLOPsBytesI_{\text{algo}} = \frac{\text{FLOPs}}{\text{Bytes}}

同时,硬件有一个固有的临界强度:

Ihw=Peak FLOPs/sBandwidthI_{\text{hw}} = \frac{\text{Peak FLOPs/s}}{\text{Bandwidth}}

两者的比较:

这个比值判定就是 Roofline 的核心。

用矩阵乘法理解临界点

矩阵乘法是 Transformer 的计算主体,也是最经典的 Roofline 分析对象。

考虑 bf16 矩阵乘法 XY=ZX \cdot Y = Z,其中 XX: bf16[BB, DD],YY: bf16[DD, FF],ZZ: bf16[BB, FF]:

算术强度:

I=2BDF2(BD+DF+BF)=BDFBD+DF+BFI = \frac{2BDF}{2(BD + DF + BF)} = \frac{BDF}{BD + DF + BF}

在推理场景中,BB(token batch size)通常远小于 DDFF(隐层维度,通常数千到上万),分母中 DFDF 项占主导:

IBDFDF=BI \approx \frac{BDF}{DF} = B

矩阵乘法的算术强度近似等于 batch size BB

以 NVIDIA H100 SXM 为例:

指标数值
bf16 密集算力9.89×10149.89 \times 10^{14} FLOPs/s
HBM 带宽3.35×10123.35 \times 10^{12} Bytes/s
临界算术强度 IhwI_{\text{hw}}295\approx 295 FLOPs/Byte

注意:NVIDIA 官方标称 H100 的 bf16 算力为 1.979 PFLOPs,但这个数字包含了 2:4 结构化稀疏加速。绝大多数 LLM 推理负载无法利用结构化稀疏,实际可用的密集算力是标称值的一半1

因此,bf16 矩阵乘法在 H100 上 compute-bound 的条件为 B>295B > 295。低于这个阈值,GPU 大量时间在等数据从 HBM 搬进来,算力被浪费。

还有一个容易混淆的细节:这里的 BBtoken 级 batch size,不是 sequence 级。一个 batch 包含 4 条长度 1024 的序列,B=4096B = 4096,远超 295,稳稳地 compute-bound。而且这里说的是 per-replica 的 batch size:如果通过模型切分把一次矩阵乘法分到多张卡上,参与这份权重副本计算的总算力和总带宽会一起扩展,所以临界 batch size 仍然按每份独立模型权重副本来算1

LLM Decode 为什么是带宽瓶颈

Transformer 的计算主体是矩阵乘法,所以上面的结论可以直接套用:Decode 阶段每步只处理 1 个新 Token(或 batch 中的 BB 个),算术强度 B\approx BB=1B = 1 时,强度仅为 1,远低于 H100 的临界值 295。Decode 在典型并发下几乎总是带宽瓶颈。

这直接解释了两个常见的工程实践:

量化降低 Decode 延迟。 bf16→int8 将权重搬运量减半,bf16→int4 减至四分之一。在带宽瓶颈下,搬运量的减少几乎等比地转化为延迟降低2

增大 batch size 提升吞吐。 增大 BB 使算术强度线性上升,逐步逼近 compute-bound 区域,更充分地利用算力。这是 continuous batching 和 vLLM 等推理引擎追求高并发的核心动机之一。

作为对比,Prefill 阶段一次性处理整个 promptBB 等于 prompt 中的 token 数(通常数百到数千),天然容易 compute-bound。这是 Prefill 和 Decode 在性能特征上的本质差异,也是 Prefill-Decode 分离调度(Disaggregated Serving)架构的理论基础。

从 Roofline 到 GPU 资源预估

这是一个探索议题,源于:既然 Roofline 能做性能分析,能不能拓展到资源预估?判断瓶颈方向和预估 GPU 数是两个不同的问题。前者是定性分析,后者则是定量分析,同时还要考虑结论能否外推。

实验设计:用单阶段能力检验 mixed E2E

这次实验先不逐项分析执行开销,而是把 mixed E2E 数据留作最后验证:

  1. 分别压测 Prefill-only 和 Decode-only,标定两个阶段的独立服务成本。
  2. 用综合效率把理论计算量和数据搬运量校准到实测能力。
  3. 根据 Roofline 推导 Prefill 在 Decode 中的 κhide\kappa_{\text{hide}}
  4. 比较同并发下 Decode-only 与 E2E 的 TPOT,并比较相同 TPOT 阈值下的 output TPS。

第一步压测得到的计算/带宽综合效率为:

ηF=FPTPFpeak,ηB=BDTDBpeak\eta_F=\frac{F_P}{T_PF_{\text{peak}}}, \quad \eta_B=\frac{B_D}{T_DB_{\text{peak}}}

FPF_PBDB_D 分别是标定 workload 的 Prefill 计算量与 Decode 数据搬运量,TPT_PTDT_D 是对应的实测时间。ηF\eta_FηB\eta_B 吸收了标定工况下的各类执行开销,表示综合有效计算效率与带宽效率。它们用于校准单阶段能力,并不分别度量每一项开销。

Prefill 只可能在同一个 mixed step 内隐藏

aPa_P 表示每个 Prefill token 的平均计算量,bDb_D 表示每个 Decode token 的平均数据搬运量,两者近似为常数。FeffF_{\text{eff}}BeffB_{\text{eff}} 是单阶段标定出的有效算力与带宽。记 tP=aP/Fefft_P=a_P/F_{\text{eff}}tD=bD/Befft_D=b_D/B_{\text{eff}},分别表示 Prefill-only 每 input token、Decode-only 每 output token 的处理时间。令一个 mixed step 同时处理 cc 个 Prefill token 和 dd 个 Decode token。若两类工作处于同一个可重叠的执行窗口,理想 step 时间为:

τ(c,d)max(ctP,dtD)=max(aPcFeff,bDdBeff)\tau(c,d) \approx \max(ct_P,dt_D) =\max\left(\frac{a_Pc}{F_{\text{eff}}},\frac{b_Dd}{B_{\text{eff}}}\right)

第一个时间小于等于第二个时间时,Prefill 计算延迟可以被 Decode 隐藏,由此得到隐藏的边界情况:

cdtDtP=FeffBeffbDaPκhide\frac{c}{d} \leq \frac{t_D}{t_P} =\frac{F_{\text{eff}}}{B_{\text{eff}}}\frac{b_D}{a_P} \equiv \kappa_{\text{hide}}

κhide\kappa_{\text{hide}} 表示同一个 mixed step 内最多能够隐藏的 Prefill/Decode token 比例。它给出资源互补条件下的理想边界,成立还要求两类工作确实共享可重叠的执行窗口,并且单阶段效率在 mixed step 中保持适用。

长期 input/output 比例仍然有用。设 IeI_e 为扣除 prefix cache 后需要实际计算的 input token 数,OO 为 output token 数,Ie/OI_e/O 决定系统长期需要完成多少 Prefill 和 Decode 工作。我们假设 Ie/Oc/dI_e/O \approx c/d。不过,scheduler 决定这些工作如何分布为逐 step 的 c/dc/d。相同的总量比例可以形成不同的 mixed step 序列,也会得到不同的重叠效果。

实验结果:无干扰近似过于乐观

在同一局部有效口径下,边界也可以直接由单阶段吞吐换算:

κhide=tDtP=Prefill-only TPSDecode-only output TPS30\kappa_{\text{hide}} =\frac{t_D}{t_P} =\frac{\text{Prefill-only TPS}}{\text{Decode-only output TPS}} \approx 30

本次压测的 input/output 比例约为 8。若把长期工作量均匀摊入每个 mixed step,Prefill 应当可以完全隐藏,即同一并发下 E2E 相对 Decode-only 的 TPOT 增量应接近零。但压测测得的增量约为 7% 至 10%;对两条曲线在同一 TPOT 阈值处插值后,E2E output TPS 比 Decode-only 低约 19%。

这可能是由于 c/dc/d 的比例实际上一直在变化。带 Prefill 的 step 中 c/dc/d 可以达到数十以上,超过约 30 的边界。没有 Prefill 的 step 即使留下算力,也不能跨 step 补偿。长期比例约为 8,并不意味着每个 mixed step 的比例都是 8。完全串行时,单位 output token 的耗时为 tD+(Ie/O)tPt_D+(I_e/O)t_P。由此预测的 output TPS 仅比实测低约 3%,说明大部分 Prefill 成本没有被隐藏。

分析:长期比例不能代替逐 step 比例

Decode 受带宽约束、Prefill 受算力约束,只说明两类工作在同一个 step 内可能重叠。令 TP,iT_{P,i}TD,iT_{D,i} 表示第 ii 个 step 中两类工作的理想耗时。先汇总长期工作量再取一次 max\max,会允许空闲资源跨 step 转移;真实执行则要对每个 step 分别取 max\max

max(iTP,i,iTD,i)imax(TP,i,TD,i)\max\left(\sum_i T_{P,i},\sum_i T_{D,i}\right) \leq \sum_i\max\left(T_{P,i},T_{D,i}\right)

因此,单阶段能力可以给出完全隐藏与完全串行两个端点,却不能单独确定 E2E 落在什么位置。

要继续做白盒预估,还需要从 workload 推出逐 step 的组成。PD 分离下,两阶段不共享 mixed step,单阶段标定也更容易用于各阶段资源量的线性外推。

结语

Roofline Model 是一个极简但有力的分析框架:两个硬件参数,一个强度比值,就能判断计算卡在哪。它直接解释了 LLM 推理中的一系列工程决策:为什么低 batch 的 Decode 容易进入带宽瓶颈、为什么量化有效、为什么增大 batch 能提升硬件利用率。

这次探索了 Roofline 在资源预估中的使用边界。Roofline 可以计算已知 mixed step 的理论下界,也可以给出理想条件下的资源重叠边界。要把它用于资源预估,还不够精细。

参考资料

  1. The Roofline Model — How To Scale Your Model 2 3

  2. LLM Inference Performance Engineering: Best Practices — Databricks


Share this post on:

Previous Post
无损投机采样的概率论视角
Next Post
PagedAttention 详解:缓存的存储结构