news 2026/11/3 13:23:57

三个公式算清大模型推理的算力上限与带宽瓶颈

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
三个公式算清大模型推理的算力上限与带宽瓶颈

算力上限和带宽瓶颈这两个词,最近在 AI Infra 的讨论里出现的频率非常高。我刚接触大模型推理加速时,最大的困惑不是“怎么调参数”,而是连一个基本问题都答不上来:这块 GPU 到底能榨出多少 token?为什么看着算力有几百 TFLOPS,跑起 7B 模型却常常只有一两百 token/s,差距大到让人怀疑表格写错了。

后来我把注意力从“参数调优”转回“量化估算”,发现只要用三个公式,就能把大模型的推理上限、带宽瓶颈和并发饱和点算得明明白白。这篇文章想把这套方法分享出来,顺便结合我最近在看的 nano-vllm 这类教学项目,做一个从公式到实测的对照思路。适合刚开始做模型部署、搞推理服务选型,或正在排查 GPU 利用率不高的同学。

1. 先搞清楚算力上限:模型参数和 FLOPs 之间的关系

1.1 理论峰值和实际可用算力之间,隔了一个“每 token 成本”

看 GPU 规格表的时候,H100、A100 的 TFLOPS 数字都很吓人,但那是跑矩阵乘法的峰值,还是靠 fp16/fp8 才能摸到的理论值。真正的大模型推理,每个 token 要经过一层又一层 Transformer,每层都要对权重矩阵做矩阵乘法,这个计算量可以直接和模型参数量挂钩。

业界一个很常用的近似:Transformer 推理每生成一个 token,前向传播的 FLOPs 约为参数总量的 2 倍。也就是:

FLOPs_per_token ≈ 2 × P

P 是模型参数量。为什么是 2 而不是 3 或者 6?训练一个 token 大概需要 6P FLOPs,因为要算前向、反向还有参数更新;推理只做前向,每个参数大概对应一次乘加操作,一次乘法一次加法就是 2 FLOPs。LayerNorm、激活函数、attention 这些也会消耗一点算力,但在整体比重里很小,入门阶段先忽略,误差通常在 10% 以内。

有了这个漏斗,第一个公式就出来了。

1.2 公式一:GPU 上单流解码的“算力天花板”

T_compute = F / (2 × P)

F 是 GPU 的可用浮点算力,单位 FLOPs/s;P 是模型参数量;T_compute 就是假设完全受算力约束时,每秒最多能解码的 token 数。

拿一张 A100 80GB 来算笔账。A100 在 FP16/BF16 下大概有 312 TFLOPS,也就是 312 × 10^12 FLOPs/s。模型用 7B 参数,那么:

  • FLOPs_per_token = 2 × 7 × 10^9 = 14 × 10^9
  • T_compute = 312 × 10^12 / 14 × 10^9 ≈ 22285 token/s

两万多的 token/s,看起来很夸张。但真去跑一个单请求,实际根本到不了这个数,甚至差两个数量级。问题不在于算力不够,而在于推理过程中还有一个比算力更先卡住你的东西:显存带宽。

2. 真正的拦路虎:HBM 带宽瓶颈

2.1 权重在显存里躺着,每个 token 都要重新“背”一遍

Transformer 推理和传统 DL 推理最大的区别是自回归:生成了上一个 token,才能算下一个 token。每生成一个 token,都要把权重从显存里完整读一遍。权重不能一直放在 GPU 的 SRAM 里,因为 SRAM 只有几十 MB,模型权重有几十 GB,必须放在 HBM 里反复读取。

这个“反复读取”就是带宽瓶颈的来源。GPU 的理论算力再高,如果数据从 HBM 到计算单元的速度跟不上,核心就只能干等。

公式二写出来非常直白:

T_bandwidth = HBM_BW / (P × bytes_per_param)

P × bytes_per_param 就是模型权重在显存里的字节数。FP16/BF16 下每个参数占 2 字节,FP8 占 1 字节,INT8 也是 1 字节。

回到刚才的例子。A100 80GB 的 HBM 带宽大约在 2TB/s 这个量级。7B 模型如果按 FP16 部署,权重占 14GB:

  • T_bandwidth = 2000 × 10^9 / (7 × 10^9 × 2) ≈ 142 token/s

你没看错,单 Token 解码的带宽上限就是一百多 token/s。这和很多人在 A100 上跑 7B 模型测到的单请求性能几乎一致。此时 GPU 算力虽然还有两万 token/s 的潜力,但权重搬运速度只允许它每秒处理一百多个 token。

这也解释了一个部署中很常见的现象:把模型从 FP16 换成 INT8 后,吞吐能接近翻倍。因为每个参数从 2 字节变成 1 字节,HBM 需要搬运的数据少了一半,带宽瓶颈自然宽了一倍。所以做推理优化,不要一上来就盯着 kernel 调优,先看看你用的精度合不合理。

2.2 KV Cache 也要吃带宽:长上下文下不能忽略

权重是第一个带宽大户,KV Cache 是第二个。生成 token 时,Key 和 Value 向量要不断写入显存,下一轮计算还要把它们读出来参与 attention。KV Cache 的大小和网络结构强相关。

简化来看,单条序列每个 token 占用的 KV Cache 字节数大约是:

KV_bytes_per_token = 2 × L × kv_heads × head_dim × dtype_size

其中 L 是层数。举个例子,一个近似 LLaMA 风格的 7B 模型,32 层、hidden size 4096、32 个 KV head、每个 head 的维度是 128,那么:

  • 每个 token 的 KV = 2 × 32 × 32 × 128 × 2 = 512KB

这个数字细想很吓人。2048 token 的上下文,KV Cache 就要 1GB。要是并发处理几十条长序列,KV Cache 会把显存吃得非常快。这也是为什么 vLLM 要专门做 PagedAttention 和 KV Cache 管理,而不是让每个请求随便分配一整块连续显存。

KV Cache 对带宽的影响在单请求场景下不明显,因为 512KB 和 14GB 权重比起来实在太小;但当 batch 很大、上下文很长时,KV Cache 的总读写量会逐渐追上来,甚至成为新的瓶颈。后面算并发临界点的时候,也要把这一项纳入考虑。

2.3 把两个公式放一起:A100 跑 7B 的真实基调

对比一下两个上限:

  • 算力上限:约 22285 token/s
  • 带宽上限:约 142 token/s

两者差了 150 倍。单请求解码的瓶颈几乎由带宽决定,测出来快接近 142 token/s 就是很健康的状态。如果连这个数都差得远,那问题不在模型或框架,而在服务链路、kernel 启动开销、batch 策略这些工程细节。

不过这里有个容易误导人的点:T_bandwidth 是单 Token 流上的极限。真实推理服务不会只服务一个用户,GPU 同时处理很多请求时,算力上限会重新变成主角。

3. 第三个公式:要填满 GPU 算力,到底需要多少并发

3.1 从“带宽受限”切到“算力受限”的临界批量

decode 阶段每个 step,服务端要处理一批 token,每个 token 都要做一次完整的权重矩阵乘。假设 batch size 是 B,那么这一步的总计算量是 B × 2P;而权重读取量只有一份 P × bytes_per_param,因为多个请求共用同一份权重,HBM 只需要把权重搬运一次,但计算单元要针对每个请求都用一次。

所以随着 batch 变大,计算时间线性增长,内存搬运时间却基本不变。总不至于永远被带宽卡住,总有某个 batch size 让计算时间大于内存搬运时间。让两者相等时的批量大小,就是临界点:

B* = (F × bytes_per_param) / HBM_BW

这个公式很有意思:它等于 GPU 的“算术强度”乘以字节大小,是硬件本身的性质,和模型参数量的关系反而不大。同一个 GPU 上,7B 和 70B 模型的临界批量基本相同,因为计算量和搬运量都随参数量同步增长。KV Cache 会在 batch 很大时改变这个结论,但作为一阶估算够用。

拿 A100 80GB 继续算。F = 312 × 10^12,BW = 2000 × 10^9,FP16 下 bytes_per_param = 2:

B* = 312e12 × 2 / 2000e9 ≈ 312

也就是说,大概 312 路并发请求同时 decode 时,计算时间和权重搬运时间才打平;在此之前,GPU 的算力是闲置的。这也解释了为什么推理服务必须做 continuous batching 而不是简单地并发几个线程:十几路请求的并发下,GPU 依然在等显存,根本触不到算力天花板。

3.2 把 KV Cache 加进临界批量,结论会怎么变

上面的 B* 只考虑了权重。如果把 KV Cache 的读写算进去,decode 阶段每 step 的内存搬运量大致是:

Mem_per_step = P × bytes_per_param + B × KV_bytes_per_token × 2

乘以 2 是因为每个 token 的 KV 要先读旧值,再写新值。带入临界条件:

B*_kv = (F × bytes_per_param) / (HBM_BW - B × KV_bytes_per_token × 2 / 时间步)

实际计算不用这么绕,更简单的方法是把 KV 读写量当成附加项,直接加在内存时间上迭代估算。用上面那个 512KB/token 的例子,300 路并发时 KV Cache 读写量大约 300MB,和 14GB 权重比还差得远,所以不会显著改变 312 这个量级。但如果你跑的是 70B 模型、长上下文、4096 并发,KV 读写就可能变成和权重等量级的存在。

3.3 用 nano-vllm 观察“并发如何吃掉空闲算力”

公式算到这里,下一步自然是动手验证。我最近在看 nano-vllm 这类专为学习而做的项目,它把 vLLM 里的核心机制抽出来做成最小实现,包括 PagedAttention、continuous batching、KV Cache 管理这些,代码量比 vLLM 本体小得多,特别适合对着源码看关键功能。

在 nano-vllm 里做验证,可以朴素一些:先用 7B 模型跑单请求,记录 decode 的 token/s,应该接近 T_bandwidth;然后逐渐增加模拟并发序列,观察总吞吐曲线。你会发现:

  • 并发从 1 加到 32,总吞吐缓慢上升,但单路 token/s 明显下降
  • 并发继续加到 200~300,总吞吐开始逼近 T_compute 的某一个百分比
  • 超过一定并发后,KV Cache 显存先不够用,总吞吐不再线性增长

这个过程比看任何论文都直观。nano-vllm 这样的项目适合把公式里每个变量和代码里的每个数据结构对上号,比如 block table 对应 KV Cache 的分页管理,continuous batching 对应调度器里的队列状态。

4. 实操中怎么用这三个公式做容量预估和压测对照

4.1 一张表快速算清典型模型部署

把公式换算到常见模型规模上,可以产出一张非常实用的估算表。前提都按 A100 80GB、FP16/BF16 精度、带宽 2TB/s、算力 312TFLOPS 来算。7B 模型权重约 14GB,13B 约 26GB,70B 约 140GB,后面两个在大 Batch 下还要考虑张量并行。

模型规模权重大小T_bandwidthT_compute显存可容纳的 KV 预算
7B14GB约 142 token/s约 22285 token/s比较宽裕,单卡可跑长上下文
13B26GB约 76 token/s约 12000 token/s单卡还剩 50GB 左右,看 KV head 数量
70B140GB需多卡,单卡约 1/8 权重,带宽瓶颈不变约 2228 token/s单张卡都不够放,必须多卡并行

注意 70B 那一行有个新手容易搞错的地方。用张量并行把 140GB 权重切到 8 张卡上时,每张卡只读 1/8 的权重,但每张卡也只用 1/8 的带宽口径,所以单序列的 token/s 不会因为多卡而变成 8 倍。真正被多卡并行放大的是显存容量,让 70B 模型能跑起来。

4.2 压测前先做的几个动作

  • 第一步:确认模型精度和参数。用model.get_memory_footprint()这类接口直接看权重的实际显存占用,别用手算的参数猜。
  • 第二步:确认 GPU 的 HBM 带宽。不同型号差异很大,A100 约 1.9~2.0TB/s,H100 约 3.35TB/s,消费级卡更小,不能拿旗舰规格乱套。
  • 第三步:把公式算出来的数字写进压测预期里。比如 7B FP16 跑 A100,单请求 decode 低于 120 token/s,先查服务本身,别怀疑 GPU 不行。

实测中很难看到纯带宽极限,因为每次 kernel 启动、CUDA graph 捕获、调度器切换都会有开销。常规的经验是:能把理论 T_bandwidth 的 70%~90% 跑出来,已经很好了;跑到 90% 以上,基本可以认为链路优化到位。

4.3 利用 CUDA 工具验证瓶颈位置

如果压测结果和公式差很多,用 nsight compute 抓一下 kernel 就很清楚了。关注两个指标:

  • SM 利用率:如果很低,但 Memory Throughput 接近 100%,说明是明显的带宽受限,继续增大 batch 或降低精度才有收益。
  • SM 利用率很高,但吞吐没有明显增长:说明已经接近算力上限,该考虑换更小模型或量化方案。

我在 nano-vllm 这类项目里常用的方式是先写一个只测 GEMV 的小 kernel,单独看看权重读取能达到多少 GB/s。用这个数字代替理论带宽,公式会贴合现实得多。很多时候瓶颈不是 HBM 本身,而是 kernel 没有把数据搬到位,比如未对齐访问、小的 tile size、过多的 launch overhead。

5. 常见问题与排查技巧实录

5.1 为什么压测值比公式低很多

这是问得最多的场景。先说结论:公式算的是理想上限,不是现实目标。如果你压测单请求 decode 只有 60 token/s,而公式给出 142 token/s,大概率是下面几种情况。

一是把 prefill 和 decode 混在一起统计了。首次生成之前要处理提示词,prefill 阶段计算密度高,但整体耗时也不小。如果压测脚本把“接收第一个 token 的时间”也算进总吞吐,数字会难看。正确做法是把 TTFT 和单 token 延迟分开计,只统计 decode 阶段的稳定输出速率。

二是 batch 策略太保守。很多部署框架默认限制了最大并发数。如果同时只有几路请求,GPU 一直处于带宽受限的等待状态,算力完全闲在那里。把 continuous batching 打开,或者手动提高 max-num-seqs,再看总吞吐变化。

三是 KV Cache 显存碎片导致的调度阻断。vLLM 的 PagedAttention 用固定块管理 KV Cache,但每块大小、preemption 策略、max-model-len 设置都会影响实际并发能力。如果显存有空间但总是 OOM,优先检查 max-model-len 和 KV 块大小。

5.2 为什么并发增加到一定程度后,总吞吐反而不涨

这是典型的从带宽受限切换到算力受限的信号。A100 跑 7B 的临界批量大概在 300 附近,当 batch 在这个量级附近时,算力开始饱和。再往上加并发,单条序列能分到的算力被摊薄,总吞吐会进入平台期。

如果平台期的总吞吐远低于 T_compute 的预期,需要检查 attention kernel 的实测性能。nano-vllm 里最值得研究的就是 attention 和 GEMV 这两个算子,因为它们一个负责 KV Cache 搬运,一个负责权重读取。把这两个 kernel 用 ncu 测透,基本就能定位性能上限在哪里。

5.3 三个公式的适用范围和局限

这套公式适合做容量预估和瓶颈定位,不适合替代完整性能建模。它假设模型权重能被完整放进显存,假设计算单元能持续跑满,假设 HBM 带宽恒定。真实系统里还有 CUDA graph 的捕获开销、显存不足触发 offload、多机通信等因素,都会让实际值偏离。

另外,量化对公式影响很大。FP8 或 INT8 下 bytes_per_param 变成 1,T_bandwidth 直接翻倍,B* 减半。如果模型做了 4bit 量化,字节数变成 0.5,那带宽上限还能再翻一倍。这不代表量化没有代价,准确率损失和反量化开销也要一起权衡。

我在实际项目里已经养成习惯:任何模型部署前,先花十分钟把三个公式算一遍,再决定精度、并发上限和压测目标。踩过几次坑之后发现,90% 的“性能差”其实在跑压测之前就能用公式预判出来。公式不会帮你把 GPU 从 60分 优化到 100分,但它能让你心里有数,知道到底应不应该继续做 kernel 层面的优化,还是换个精度、换个模型、换张卡更划算。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/3 13:23:57

若依前后端分离部署实战:版本对齐、Nginx/Tomcat配置与故障排查

简介:围绕若依前后端分离项目的实际部署,这份 Word 文档给出了一套可对照操作的流程记录,面向已具备 Spring Boot 与 Vue 基础、正准备把项目搬上服务器的初中级开发者。内容分三条主线展开:Linux 环境下打包 jar 与 dist、配置 N…

作者头像 李华
网站建设 2026/11/3 13:23:49

buzz本地语音转文字工具:模型选型、安装避坑与离线转写实操指南

1. 项目拆解:buzz到底是个什么“热词” 最近一段时间,如果你常刷效率工具相关的社群和论坛,大概率会在标题里反复看到一个词——buzz。一开始我以为它只是单纯指“话题热度”或者“讨论度”,但后来发现它其实落到了一个非常具体的…

作者头像 李华
网站建设 2026/11/3 13:23:47

伯恩斯坦多项式与贝塞尔曲线的数学原理及应用

1. 伯恩斯坦多项式与贝塞尔曲线的数学渊源 伯恩斯坦多项式这个看似抽象的数学概念,实际上在计算机图形学领域有着举足轻重的地位。我第一次接触这个主题是在开发一个矢量图形编辑器时,当时需要实现平滑的曲线绘制功能。经过反复尝试后发现,理…

作者头像 李华
网站建设 2026/11/3 13:23:05

技术项目环境准备与部署最佳实践指南

1. 环境准备与安装部署概述 在开始任何技术项目前,环境准备都是最基础也是最重要的环节。就像盖房子需要先打地基一样,一个稳定、可靠的环境是后续所有工作的基石。我见过太多项目因为环境问题而中途夭折,也亲身经历过因为环境配置不当而导致…

作者头像 李华
网站建设 2026/11/3 13:22:06

MAXIMO二开入门:页面、工作流与Mbo持久层开发排错

简介:《Maximo入门培训》面向刚接触企业资产管理系统的开发与实施人员,帮助读者从基础概念过渡到实际定制开发,适合需要了解 Maximo 技术架构、页面与工作流开发及数据库配置的初中级学习者。资料为 1 个 docx 文档,压缩包约 436K…

作者头像 李华
网站建设 2026/11/3 13:21:40

基于浏览器插件的智能喝水提醒系统开发实践

1. 项目背景与核心价值 作为一个长期伏案工作的程序员,我发现自己经常一整天都想不起来喝水。直到某天体检发现尿酸偏高,医生提醒每日饮水量严重不足,才意识到问题的严重性。于是萌生了开发浏览器喝水提醒插件的想法——毕竟现代人80%的工作时…

作者头像 李华