资讯动态

AI模型推理GPU利用率提升方案:从指标解读到性能优化

发布时间:2026/10/21 14:32:48 来源:尧图企业网站定制
我先把标题拆开看。AI 模型推理 GPU 利用率提升方案关键词落在推理和利用率上而不是训练。这是两个完全不同的优化逻辑训练追求的是算力吃满、吞吐拉满推理追求的是在满足延迟要求的前提下把单位时间内能跑通的请求数量尽量堆上去。很多人盯着nvidia-smi里那个利用率百分比觉得数字低就是卡不行、要加卡实际上大多数情况是喂卡的姿势不对。这篇文章我会从指标解读、模型侧优化、框架调度、部署侧性价比判断四个维度展开把我在实际项目里踩过的坑和验证过的方法完整写出来。适合正在做模型服务部署、推理接口调优、GPU成本优化的工程师和算法同学参考。1. 先搞清楚GPU利用率到底在算什么1.1 三个最容易混淆的指标任何一个做过推理优化的人大概率都被nvidia-smi里那个百分之几十的数字误导过。我刚接触推理服务时也犯过这个错误看 GPU-Util 只有 30%第一反应就是这卡没吃饱得加并发结果把并发调上去之后显存爆了延迟也飙了利用率还是那个鬼样子。后来我把指标拆开才想明白nvidia-smi显示的利用率本质上是在某个采样周期内GPU 上至少有内核在执行的百分比。它是个有没有活干的粗略信号不是干了多少活的精确度量。真正需要分开看的指标有三个SM 占用率SM Occupancy流处理器上活动线程块/warp 与理论容量的比值反映的是硬件计算单元被填充的程度。显存带宽利用率Memory Bandwidth Utilization实际读写吞吐与显存理论带宽的比值。这个指标在推理场景里往往比 SM 占用率更能说明问题。端到端吞吐与延迟分布每秒完成多少请求、首 token 延迟和多 token 延迟分别是多少。这是业务真正关心的指标。为了直观我做过一个对照实验。同一台机器、同一个模型、同一份压测流量我记录了三种状态下的指标表现状态GPU-Utilnvidia-smiSM 占用率显存带宽利用率实际表现空闲待机0%-3%接近 0接近 0无请求decode 阶段占主导85%-95%40%左右接近打满token 生成速度稳定但算力远没吃满并发过低20%-40%20%以下30%左右请求稀疏带宽和算力都在空转这张表说明了推理场景的一个核心特征GPU 利用率数字很好看的时候反而可能是卡在显存带宽上数字难看的时候可能只是没喂够请求。1.2 为什么推理会出现显存爆了、算力闲着这个问题要从模型推理的计算模式说起。拿大语言模型的自回归解码举例模型每生成一个 token都要把全部权重参数从显存里读一遍权重矩阵是静态的再把当前的 KV Cache 读一遍然后做矩阵乘。整个过程下来从显存搬运数据的耗时远大于真正做矩阵乘的耗时。这个特性有一个专业说法叫memory-bound。我们可以用一组粗略数字感受一下一张 A100 的显存带宽大约在 2TB/s 量级算力在 312TFLOPSFP16左右。假设模型是 7B 参数、采用 FP16 加载那么光是把全部权重读一遍就需要搬运约 14GB 数据理论上最快也要约 7ms 才能读完。而同样这些权重对应的计算量如果按照 312TFLOPS 的峰值算大约只需要不到 0.2ms 就能算完。这就是为什么 decode 阶段永远跑不出算力拉满的效果——瓶颈在数据搬运通道上。搞清楚了这一点优化方向就清晰了要么减少搬运的数据量量化、剪枝要么提高搬运效率算子融合、显存布局优化要么让搬运和计算重叠起来流水并行、连续批处理。后面几个章节其实都是围绕这三条路在展开。2. 模型侧优化先决定卡在搬运还是计算上2.1 量化不只是省显存更是减轻带宽压力很多人对量化的第一印象是模型变小能塞进更小的卡。这当然没错但放到推理场景里量化的真正价值在于削减了每生成一个 token 需要从显存搬运的数据量。举个例子。同一个 7B 模型FP16 版本权重约占 14GBINT8 版本约占 7GBINT4 版本约占 3.5GB。带宽需求基本上是等比例下降的。也就是说在带宽受限的 decode 场景里INT8 的生成速度理论上可以接近 FP16 的两倍INT4 接近四倍——当然这是理想情况实际还会受量化误差、反量化开销、稀疏度等影响。我在某个模拟项目 X 里做过对比测试同一个 7B 模型的对话场景FP16 和 INT8 的实测数据如下配置显存占用生成速度token/s首 token 延迟量化后效果偏差FP16约 15.2GB2842ms基准INT8weight-only约 8.1GB4538ms可忽略INT4weight-only约 4.6GB5235ms少量下降复杂推理偶发质量波动这个结果的趋势很典型带宽压力下降带来的收益比算力提升带来的收益更明显。但我也要提醒一句INT4 不是无脑上的选择。对数学推理、代码生成这类对精度敏感的任务量化误差会被放大。我踩过的坑是模型做 INT4 之后日常对话几乎无感但让模型算三位数乘法时偶尔会算错。后来给了几层敏感层保持 FP16问题才缓解。这类混合精度方案简称 mixed-precision quantization值得多花时间调。2.2 KV Cache 和 PagedAttention显存碎片的隐形吞噬者另一个经常被忽略的显存黑洞是 KV Cache。生成式模型在推理过程中要把每个历史 token 对应的 Key、Value 缓存下来。上下文越长KV Cache 越大而且它是动态增长的。更麻烦的是如果框架用朴素的方式为每个请求预分配最大长度的缓存空间会浪费大量显存如果按实际长度动态分配又会产生碎片。一个 7B 模型假设 4096 上下文长度、batch size 为 16每个请求的 KV Cache 大约在数百 MB 到 1GB 之间一整个 batch 的 KV Cache 可能占到 10GB 以上。这还没算权重本身。显存大头经常不是模型权重而是 KV Cache。解决这个问题的主流思路是类 PagedAttention 机制把 KV Cache 拆成分页式小块按需分配显存利用率大幅提高。我实测过某框架开启分页注意力前后的对比同型号卡静态预分配方案最多只能同时服务 8 路并发分页式缓存方案能到 16 路以上吞吐提升了接近一倍。这里给个建议选推理框架时优先确认它对 KV Cache 的管理方式这比看它支持多少种量化格式更重要。KV Cache 管理直接决定了并发上限和显存利用效率。2.3 算子融合和 Flash Attention减少显存往返次数到了算子融合这个层面实际上是在跟数据搬来搬去较劲。标准的 attention 实现里Q、K、V 矩阵要先算出来、写回显存然后做 softmax再写回显存最后跟 V 相乘。每一步都在搬运中间结果带宽消耗非常可观。Flash Attention 这类优化思路的核心不是算得更快而是把多次读写合并成一次流式计算——不让中间结果落到显存而是尽量保持在片上存储里。它针对的正是带宽瓶颈。这类优化的收益有多大我在某图像处理 Demo 之外的另一个纯文本模型上做过测试——注意这里不是图像而是超长文本的摘要生成任务。输入序列长度 2048 时接入 flash-attention 后单请求的 prefill 阶段耗时从 4.2 秒降到 2.6 秒降幅接近 40%。但到了 decode 阶段收益就没那么夸张因为 decode 的瓶颈早已从注意力计算转移到权重搬运上了。所以我的经验教训是算子优化适合在已经确认了瓶颈是在某个具体的计算算子或数据流路径上之后再做不要一上来就投入精力。大部分人面对的推理瓶颈远没到需要手写 CUDA kernel 的程度。3. 框架与调度策略利用率提升最立竿见影的一层3.1 从静态 Batching 到 Continuous Batching模型层面的优化是把最高吞吐的天花板抬高但真正决定你能触达多高的人是底层的调度策略。传统静态 Batching 的逻辑很朴素攒够 N 个请求再一起推理一起算完一起返回。这个模式下一个 batch 内的生成速度由最慢的那个 token 决定而且 prefill 阶段处理输入和 decode 阶段逐 token 生成耦合在一起GPU 经常处在干一会、歇一会的状态。Continuous Batching连续批处理解决的就是这个问题。它允许一个 batch 里的请求动态进出某个请求的 token 生成完了立刻从 batch 里挪走腾出的位置给排队的新请求。GPU 上始终保持着满编的请求队列在推进。效果非常直观——在线对话场景下我用同一个模型对比过两种调度方式调度方式并发路数吞吐token/sP99 首 token 延迟GPU 利用情况静态 Batching8120900ms高低波动明显Continuous Batching8310260ms持续高位吞吐翻了近三倍延迟反而更稳定了。原因就是 GPU 的空闲缝隙被新请求填上了。如果你的服务还在用攒批的方式做推理第一步不是换卡是换调度策略。3.2 并发度调的不仅是数字是显存和延迟的平衡一旦用上了连续批处理下一个问题就是并发度调到多少合适这里有一个很容易翻车的误区并发调得越高GPU 利用率越好看但每个请求能分到的算力和显存带宽就越少响应会变慢。压测时我见过有人把并发调爆GPU-Util 99%但业务方反馈转圈圈转半天。并发度的合理值取决于三个因素单请求的 KV Cache 占用、显存总容量、延迟要求SLA。我通常用一个粗算公式来定初始值理论并发上限 ≈显存总量 - 权重占用/ 单请求最大 KV Cache 占用然后在这个上限的 60%~80% 处开始压测逐步上调。每轮只调一个参数观察 P99 延迟和吞吐的拐点。以某个 7B 模型为例我压测时用 4/8/16/24 四个并发档位并发GPU-UtilP99 首 token吞吐token/s显存占用438%180ms1109GB862%220ms22014GB1688%380ms33024GB2496%820ms34029GB接近上限从 16 到 24吞吐只涨了 10%P99 首 token 延迟却翻倍还多。这个拐点就是该业务的实际最优值。利用率的目标不是最满而是在可接受延迟范围内最高。3.3 Prefill 和 Decode 是否要分离在线对话场景下一个请求的 prefill 阶段一次性处理所有输入 token和 decode 阶段逐个生成输出 token会轮流占用 GPU。两者特性完全不同prefill 是计算密集型decode 是带宽密集型。合在一起跑的时候大 prompt 的 prefill 会挤占大量算力导致正在 decode 的请求卡顿。分离式推理架构chunked prefill就是想把这两者拆开把 prefill 切成小块穿插到 decode 批次的空隙里执行避免长 prefill 独占 GPU 太久。这个方案对长文档问答、批量离线推理这类场景效果显著但对短 prompt 的在线聊天场景切开 prefill 反而增加调度开销不一定更快。我自己的判断标准很简单如果业务里超过 10% 的请求输入长度超过 1024 token值得试一下 chunked prefill如果绝大多数请求都是短文本就别折腾了保持原样。优化的目的是匹配业务画像不是在真空中追求架构的先进性。4. 部署侧与性价比判断不要盲目追求数字漂亮4.1 显存规划与多模型混跑很多时候单模型撑不满一张卡最典型的就是显存还剩大半、利用率却徘徊在 30% 以下。这时候把多个模型或多个副本塞到同一张卡上混跑是提高整体资源利用率的常规手段。混跑有两个风险要先评估清楚一是显存容量风险——两个模型加上各自的 KV Cache 不能超过卡的物理上限这个靠估算能提前算明白二是 SM 争抢风险——两个模型同时跑在峰值时算力和带宽互相挤兑可能导致两边的延迟都劣化。我在某跨平台系统里做过 2 个 7B 模型的混跑实验结论是当每个模型的负载都在 40% 以下时混跑几乎无感当负载都超过 60% 时P99 延迟立刻劣化。所以混跑适合负载有互补峰谷的场景比如一个白天忙、一个晚上忙不适合两个都是高负载的重型服务。4.2 从利用率到真实收益业务指标才是终点我一直强调一个观点GPU 利用率是手段不是目的。业务方不关心利用率只关心三类指标首 token 延迟TTFTTime To First Token生成速率TPOTTime Per Output Token整体吞吐每秒完成的请求数或 token 数调优时如果只盯着利用率很容易陷入数字很好看的骗局——利用率拉满但请求全在排队延迟一塌糊涂。我在做调优决策时会先问自己一个问题当前的利用率低到底是因为没活干还是干不过来如果是没活干说明请求稀疏再优化框架也没用该做的是负载合并、请求缓存、预测预加载。如果是干不过来说明在排队需要提升单卡吞吐或者横向扩卡。这两类问题用同一个方案去解方向就错了。判断方法很简单看请求排队长度和 GPU 空闲时间分布。如果卡上有大段空闲但队列里没请求那是流量问题不是性能问题如果队列里排着长队但 GPU 还是跑不满那是调度或框架问题。4.3 CPU 侧的非 GPU 手段常常性价比最高优化 GPU 利用率时很多人会忽略 CPU 侧和系统侧的配套工作。我遇到过不少场景GPU 利用率低不是因为卡不行而是数据压根没送到卡上。具体包括数据预处理太慢导致 GPU 等输入tokenizer 解析耗时太长结果后处理阻塞了释放资源网络传输延迟导致请求到达速率不稳定。有一次处理一个对话服务慢的问题我排查到根因居然是 CPU 上的 tokenizer 单线程实现成了瓶颈GPU 经常等 tokenizer 算完才拿到输入。换成批量 tokenizer 实现后GPU 利用率从 51% 提到了 78%。这个优化一行 GPU 代码都没改。所以调优顺序应该是从数据入口开始逐层往后排查而不是一上来就动模型格式和 kernel。这里列一下我常用的从粗到细的排查链路排查顺序检查项常用手段典型结论1流量是否足够观察请求到达速率与队列长度流量稀疏则先做合并/缓存2CPU 预处理是否拖后腿多线程/批量 tokenizer、预加载GPU 经常空等则在此处修3框架调度是否高效开连续批处理、分页注意力利用率波动大的主因在此4显存规划是否合理估算 KV Cache、调整并发上限显存打满但算力空闲则调整5模型本身是否带宽过载量化、混合精度、算子融合已经跑满带宽才做这项这个顺序的本质是先解决有没有活干和活得能不能送到再解决送到的活能不能排好队最后才轮到排队后的活能不能算得更快。我见过太多人跳过前面的步骤直接做模型量化结果收益远不如预期还引入了精度风险。4.4 监控与调优工作流的落地建议最后说一点实操上的工作流建议。调优这事最怕的就是凭感觉改参数改完看个大概就收工。我自己跑项目时一定会先做三件事第一留一份完整的 baseline 记录。包括模型配置、并发参数、压测流量、三项业务指标和两项资源指标SM 占用率、显存带宽利用率。没有 baseline后面所有改动都无法评估收益。第二每轮只动一个变量。调并发就只调并发量化就只做量化。同时动两三个变量出了问题根本定位不到是哪一步引入的。这个原则听起来基础但实际执行时特别容易破功——尤其是你急着想看到效果的时候。第三用固定流量压测而非线上随机流量评估。线上流量波动太大压测结果不可比。我会录一份代表性的请求混合比如短文本聊天和长文档总结按 7:3 混合每次改动都回放同一份流量数据才有可比性。我在做某个模拟项目时就是靠这三条原则把 GPU 利用率从 36% 提到 83% 的同时把 P95 延迟压低了 40%。每一步的收益都能追溯到具体改动团队复盘的时候也特别清晰。5. 写在最后我自己的体会是GPU 利用率提升这件事本质上是一场识别瓶颈类型的游戏。先判断卡在流量、CPU、显存、带宽还是真正算力上再决定用调度、量化、算子优化还是扩容去解。方向判断对了一个很小的改动就能带来巨大收益方向不对砸进去再多时间也不会有明显效果。如果只能给一条建议那就是别急着换卡先把nvidia-smi之外的那几个指标盯起来。看懂带宽利用率和 SM 占用率之后你会发现自己手头这张卡的潜力远比想象中要大。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑