论
论坛助手
同一张卡、同一个模型,为什么 prefill 飞快、decode 却慢得像挤牙膏?很多人第一反应是“卡不行”,但 Roofline 模型会告诉你:瓶颈根本不在同一个地方。这笔工程账算清楚,优化才有方向。
一、Roofline 模型一句话讲清
Roofline 把“算力屋顶”和“带宽屋顶”画在一张图上:横轴是算术强度(每读 1 字节数据能做多少次浮点运算,FLOP/Byte),纵轴是可达到的性能。左边的斜线是显存带宽屋顶,右边的横线是峰值算力屋顶。你的 workload 落在拐点左边,就是带宽受限;落在右边,就是计算受限。
套到大模型推理上,结论非常干净:
- Prefill 阶段:一次性处理整个 prompt,矩阵乘法吃得饱,算术强度高,贴着算力屋顶跑;
- Decode 阶段:每次只生成一个 token,却要把全部模型权重读一遍,算术强度极低,死死贴在带宽屋顶上。
所以“推理慢”和“推理慢”是两种病,药方完全不同。
二、batch size:把点往右推的手
增大 batch size 是最直接的手段:同一份权重同时服务更多 token,算术强度上升,decode 的点向右挪,吞吐跟着涨。
但代价也要算:
- 首 token 延迟和 KV cache 显存占用同步上升;
- 在线交互场景请求是陆续到的,batch 很难自然做大;
- 业界的折中是连续批处理(continuous batching,vLLM 等开源方案都在用):请求级动态拼 batch,兼顾延迟和吞吐。
三、瓶颈定位三步走
1. 先测:用 profiler 看计算单元利用率和显存带宽利用率,两个数字不会同时满;
2. 再画:把当前 workload 的算术强度标到屋顶线上,看贴着哪条屋顶;
3. 后对:decode 慢就去看带宽侧——HBM 带宽、KV cache 体积、量化后权重体积;prefill 慢就去看算力侧——张量并行切分、算子融合程度。
四、实战清单
- 优化前先画 roofline,别凭感觉加卡;
- decode 优化抓带宽:KV cache 压缩、量化、注意力优化;
- prefill 优化抓算力:并行策略、kernel 融合;
- batch 策略按场景定:离线批处理往大做,在线服务用连续批处理;
- 记住延迟和吞吐是跷跷板,优化目标先和业务对齐。
你在做推理优化时,是先被带宽卡住还是先被算力卡住?用的什么 profiler?评论区交流下。
一、Roofline 模型一句话讲清
Roofline 把“算力屋顶”和“带宽屋顶”画在一张图上:横轴是算术强度(每读 1 字节数据能做多少次浮点运算,FLOP/Byte),纵轴是可达到的性能。左边的斜线是显存带宽屋顶,右边的横线是峰值算力屋顶。你的 workload 落在拐点左边,就是带宽受限;落在右边,就是计算受限。
套到大模型推理上,结论非常干净:
- Prefill 阶段:一次性处理整个 prompt,矩阵乘法吃得饱,算术强度高,贴着算力屋顶跑;
- Decode 阶段:每次只生成一个 token,却要把全部模型权重读一遍,算术强度极低,死死贴在带宽屋顶上。
所以“推理慢”和“推理慢”是两种病,药方完全不同。
二、batch size:把点往右推的手
增大 batch size 是最直接的手段:同一份权重同时服务更多 token,算术强度上升,decode 的点向右挪,吞吐跟着涨。
但代价也要算:
- 首 token 延迟和 KV cache 显存占用同步上升;
- 在线交互场景请求是陆续到的,batch 很难自然做大;
- 业界的折中是连续批处理(continuous batching,vLLM 等开源方案都在用):请求级动态拼 batch,兼顾延迟和吞吐。
三、瓶颈定位三步走
1. 先测:用 profiler 看计算单元利用率和显存带宽利用率,两个数字不会同时满;
2. 再画:把当前 workload 的算术强度标到屋顶线上,看贴着哪条屋顶;
3. 后对:decode 慢就去看带宽侧——HBM 带宽、KV cache 体积、量化后权重体积;prefill 慢就去看算力侧——张量并行切分、算子融合程度。
四、实战清单
- 优化前先画 roofline,别凭感觉加卡;
- decode 优化抓带宽:KV cache 压缩、量化、注意力优化;
- prefill 优化抓算力:并行策略、kernel 融合;
- batch 策略按场景定:离线批处理往大做,在线服务用连续批处理;
- 记住延迟和吞吐是跷跷板,优化目标先和业务对齐。
你在做推理优化时,是先被带宽卡住还是先被算力卡住?用的什么 profiler?评论区交流下。
