资讯动态

AI推理服务何时该上多GPU?先榨干单卡优化再说

发布时间:2026/9/10 7:42:59 来源:尧图企业网站定制
上周有同事跑过来问我“现在线上推理服务用一张 A800 跑 13B 的模型最近请求量上来了经常 OOM延迟也飘得厉害是不是该直接上多 GPU 了”我第一反应不是给他答案而是拉他坐下把现象一条条对了一遍。做 AI 推理服务这些年“单卡不够就上多卡”这个思路听上去顺理成章但实际落地时我见过太多人花了几万块的硬件成本最后吞吐没涨多少延迟反而更难看。多 GPU 不是万能药它是一把需要明确适应症才该动的手术刀。这篇文章我就围绕一个核心问题展开AI 推理服务的单卡确实撑不住了那到底什么时候该上多 GPU什么时候不该上。我会从瓶颈判断、单卡优化空间、多卡并行方案选型、实操迁移步骤、常见坑位排查这几个角度把这件事讲透希望能帮你省下不必要的硬件成本和加班时间。1. 先判断“单卡不够”到底是哪不够显存、算力还是吞吐很多人的第一反应是“显存爆了就上多卡”这是最大的误区。推理服务的瓶颈至少可以拆成三类显存容量、算力吞吐、并发与调度能力。三者表现相似但解法完全不同搞错了方向加多少张卡都白搭。1.1 显存瓶颈模型权重和 KV Cache 的真实占比先说最直观的显存限制。大模型推理时显存主要被三块东西吃掉了模型权重、KV Cache、以及中间激活值。模型权重这块很好算13B 模型 FP16 精度下光权重就是 13 × 2 26GB 左右7B 模型大概 14GB。但很多人没意识到KV Cache 才是推理场景下最容易爆显存的元凶。我举个例子。用 7B 模型假设有 32 层、KV heads 总数 32、每个 head 的维度是 128K 和 V 各一份FP16 存储那每个 token 的 KV Cache 大小大概是2 × 32 × 32 × 128 × 2 字节 ≈ 524KB。看起来不多但如果系统里同时有 100 个请求每个请求上下文平均 1024 token这就意味着 KV Cache 要吃掉 100 × 1024 × 524KB ≈ 50GB 显存。你权重才占 14GBKV Cache 反而成了大头。所以判断显存瓶颈不能只看“模型多大”要看你服务的并发数和序列长度。如果 OOM 频率随着并发上涨而明显增加多半就是 KV Cache 爆了。这时候上多卡是有效的因为你可以把权重和 KV Cache 一起分摊到多张卡上。但如果你只是并发高、显存没爆那问题的核心可能根本不在显存。1.2 算力瓶颈GPU 利用率高但延迟依然下不来另一种常见情况是显存还很充裕但 GPU 利用率长期拉满请求排队严重P95 延迟从 300ms 一路飙到 3 秒以上。这属于典型的算力瓶颈。推理时的算力消耗主要集中在 Decode 阶段也就是一个 token 一个 token 往外蹦的时候矩阵乘法的计算量并不小。判断算力瓶颈有几个指标可以参考GPU 利用率nvidia-smi 里的 Util、Decode 阶段每个 token 的生成时间TPOTTime Per Output Token、以及首 token 延迟TTFT。如果 GPU Util 已经接近 100%TTFT 和 TPOT 都在往上走那说明单卡的浮点计算能力确实见顶了。这种场景下加卡是有意义的但选多卡的方案要慎重因为纯数据并行能提升的是吞吐单请求的延迟未必能降下来。这里我插一句训练和推理的差别因为很多人喜欢拿训练时“显存不够用”的思路套推理。训练场景看的是总显存大小和整体吞吐你不在乎单个 batch 里某几个样本的延迟但推理是面向线上请求的延迟和吞吐都要保障。显存测算方式也不同训练主要看权重、梯度和优化器状态推理主要看权重和 KV Cache。你拿训练 70B 模型的显存需求来给推理服务做规划大概率会估算偏大。1.3 并发瓶颈GPU 没跑满但请求照样排队第三种隐藏很深的瓶颈是并发与调度瓶颈。表现是GPU 利用率不高只有 30%~50%显存也还有余量但请求就是排队延迟很大。这种情况往往出现在你用了比较简陋的推理方案时比如直接用 Transformers 库的 generate 接口一次只处理一个请求或者自己在外面套了一层很粗糙的同步锁。这里问题不在 GPU 算力而在推理框架的批处理能力。GPU 是典型的吞吐型硬件它最喜欢“一次喂一大把数据进来算”如果请求被串行化GPU 就一直在空转表面上“不够用”实际上根本没被用满。遇到这种情况你需要的根本不是多 GPU而是先换一个能自动做 Continuous Batching 的推理框架vLLM、TensorRT-LLM 这类把单卡的吞吐先拉起来再看要不要加卡。1.4 还不确定用这几个信号做快速判断我根据实际排查经验整理了一个对照遇到“单卡不够”的反馈时先按这个思路捋一遍现象优先怀疑的瓶颈先尝试的动作请求一多就 OOM显存监控打满显存容量不足多为 KV Cache限制并发、缩短 max length再考虑加卡GPU 利用率 95% 以上请求延迟高算力吞吐不足量化、减批处理延迟再考虑加卡GPU 利用率低于 50%但请求排队框架调度、批处理能力弱换 vLLM 等支持连续批处理的框架显存经常有碎片利用率波动大显存管理效率低开 PagedAttention或重启服务观察一句话总结显存不够是一回事算力不够是另一回事调度差是第三回事。只有前两种确实存在且优化空间已用完的情况下多 GPU 才是正确的下一步。调度问题你用多 GPU 去解决只会把复杂度翻倍。2. 上多卡之前单卡的“剩余价值”还能再榨一波很多人在单卡还没压榨到位的情况下就急着加卡结果很尴尬加了卡之后单卡利用率反而降得更低因为多卡之间的通信开销把收益吃掉了。所以我强烈建议做多 GPU 方案之前先把下面这几件事测一遍。如果做完这些之后性能提升明显那说明你根本不需要加卡如果做完之后还是不行你才真正有底气说服团队投入硬件成本。2.1 低精度量化的收益和代价量化是把模型权重从 FP16 降到 INT8、INT4 甚至 FP8 的操作直接缩小模型权重占用的显存。拿 13B 模型来说FP16 权重约 26GBINT8 后约 13GBINT4 后约 6.5GB。权重省下来的显存等于变相让 KV Cache 有更大空间能撑住更高的并发。但量化不是免费的午餐。INT4 量化会带来一定的精度损失有些对输出质量敏感的生成类任务代码生成、数学推理、长文档抽取可能会出现可感知的效果下降。我的经验是7B 以下的小模型建议谨慎用 INT413B 以上可以先试 INT8 或 AWQ/GPTQ 这类训练后量化方案用验证集跑一遍对比指标再决定是否上线。FP8 如果在你的硬件上支持比如 H 系列的 Transformer Engine通常效果接近 FP16是很划算的选项。2.2 推理框架的批处理优化比你想的更值钱如果你还在用最原始的 generate 方式那“单卡不够”很可能是个伪命题。换成 vLLM 后单卡吞吐翻两三倍是很常见的事。vLLM 的核心是 PagedAttention 和 Continuous Batching前者把 KV Cache 切成分页式的块解决了显存碎片问题后者允许一条生成流里的不同请求动态加入或离开 batch把 GPU 的算力尽量填满。实际操作上你需要调的是这几个参数max-num-seqs并发序列数、gpu-memory-utilization允许使用的显存比例、max-model-len上下文长度上限。很多人为了“保险”把 gpu-memory-utilization 设成 0.7导致 KV Cache 空间严重不足并发一上来就 OOM。在我自己的实践里如果服务比较干净、不需要留太多显存给别的进程0.9 是可以用的。max-model-len 也要根据业务实际长度来设别盲目设成 32K否则 KV Cache 预留会吃掉大量显存。2.3 单卡优化后的“验收线”做到什么程度才算压榨到位这里我分享一个自己用的判断标准如果你的单卡在做完量化、换上新框架、调好并发参数之后依然满足下面任意一条才认真考虑多 GPU单卡显存已经长期处于 90% 以上且并发数和序列长度已经是业务硬性要求无法再压缩。GPU 利用率在压测时持续超过 90%且 TPOT 依然达不到 SLO比如每 token 超过 50ms。模型单卡放不下权重和 KV Cache 加一起超出显存连低配并发都跑不起来。如果只是偶尔峰值冲高大部分时间利用率一般我更建议你用弹性策略控制并发 排队 限流把单卡撑住。毕竟多卡不光是买卡的钱还有功耗、机位、运维复杂度这些成本算下来并不低。我自己就见过有人为了“双卡更稳”上了两块卡结果每月整体成本涨了近一倍P99 延迟却只下降了 15%性价比非常差。3. 多卡方案怎么选别急着上张量并行先分清这三种路线如果你真的走到了需要多卡这一步恭喜你已经在认真考虑性能优化了。但多 GPU 不是简单“插上第二块卡”就完事并行策略选错了性能甚至比单卡还差。推理场景常见的多卡部署方式主要有三种张量并行Tensor Parallelism、数据并行Data Parallelism、GPU 实例隔离MIG/多卡多实例。三者的思路完全不同适用场景也完全不同。3.1 张量并行TP模型太大放不下时的解法张量并行是把一个模型的权重拆开分别放到多张卡上每张卡负责一部分计算。以 Transformer 里的线性层为例可以把权重矩阵按列切分两张卡各算一半最后通过 all-reduce 把结果合并。这种方式适合模型太大、单卡根本放不下的场景比如 70B、百亿级参数或者你的 KV Cache 预算很高单卡装不下。但 TP 对硬件通信的要求极高。因为每过一个 Transformer 层就要做一次跨卡同步如果卡间走的是 PCIe 而不是 NVLink 这类高速互联通信开销会非常感人。我实测过同一个模型TP2 在 NVLink 环境下吞吐损失大约在 5%~15%但如果跨节点走万兆网性能直接崩掉。所以在推理场景TP 一定要保证所有卡在同一个物理节点上最好卡之间是 NVLink 直连否则别碰。vLLM 启动 TP 很简单指定 --tensor-parallel-size N 就行它会自动把模型切分到多卡。第一次加载会比较慢因为需要做权重切分但加载完之后的推理过程是正常的。3.2 数据并行DP并发上限不够时的常规解数据并行跟 TP 的思路完全相反它不切分模型而是把同一个模型复制成多份每张卡上放一个完整副本然后前面挂一层负载均衡把请求分到不同的卡上处理。这本质上就是一种水平扩展非常适合模型能单卡放下、但并发量太大导致单卡吞吐不够的场景。DP 最大的优点是实现简单、稳定性好。你不需要关心模型怎么切每张卡独立运行自己的推理服务即可。前置可以用 Nginx、HAProxy或者直接用 Triton Inference Server 的模型副本能力来做路由。我见过不少团队在 7B/13B 模型上就是用“vLLM 启动 4 个实例 Nginx 轮询”的方式轻松扛住了几十路并发请求。DP 的注意点在于各实例之间的负载要尽量均匀。如果是简单轮询碰到某几个耗时特别长的请求被分到同一张卡上就会导致局部过载。更稳的做法是用 least_conn 之类的负载均衡策略或者按请求量做动态路由。3.3 MIG 和多实例隔离多租户场景下的折中方案MIGMulti-Instance GPU是 NVIDIA 在 A100/H100 上提供的 GPU 实例切分能力可以把一张物理卡切分成多个独立的 GPU 实例每个实例有独立的显存和计算资源。如果你们团队内部有多个小模型、或者要给不同业务线做资源隔离MIG 可以避免“一个任务把整卡显存吃光、其他人全部受影响”的问题。但推理场景下 MIG 的价值比较看情况。如果你跑的是大模型MIG 的显存分割粒度可能不够灵活切出来的实例要么显存不够放下完整模型要么算力过强但显存太小两头别扭。我更倾向于把 MIG 用在多租户小模型、或者开发和测试环境隔离上生产大模型推理的核心方案优先考虑 TP 或 DP。3.4 流水线并行PP推理场景里基本不推荐流水线并行是把模型按层切成多段每张卡负责其中几层数据按顺序流过各卡。训练大模型时 PP 是成熟方案但推理时每层要被串行流过带来的是“请求必须穿过所有卡”的固定延迟。相比 TP 的并行计算 合并PP 在 latency 上天然吃亏。所以目前主流的推理框架对 PP 的支持和优化都远不如训练场景除非模型大到 TP 都无法分割比如超大规模 MoE否则推理阶段我不建议优先考虑 PP。为了让你直观做决策我把三种主路线的适用范围整理成了表方案适用场景对通信的要求主要优势主要风险张量并行模型单卡放不下、请求延迟敏感极高建议 NVLink单请求延迟低通信开销扩展性有限数据并行模型单卡放得下、并发高低简单稳定弹性好负载均衡要处理资源利用率可能不均MIG/多实例多租户、小模型、资源隔离无特别要求隔离性好切分粒度不灵活显存利用率低选型逻辑我总结为一句话模型放不下就 TP模型放得下但请求多就 DP既要隔离就要 MIG。别一上来就搞混合并行那复杂度不是一般人能扛的。4. 从单卡迁到多卡环境检查、启动配置和性能验收确定了方案之后就进入实操阶段。很多人以为多卡就是改一个参数其实环境层面的坑非常多。我把整个迁移过程拆成几步每一步都交代清楚为什么要这么做。4.1 硬件和驱动环境检查很多坑从这里开始多卡部署前先把硬件拓扑摸清楚。命令很简单nvidia-smi topo -m这个命令会打印出各卡之间的互联方式。如果输出显示卡与卡之间是 NVLink那 TP 方案的优势能发挥出来如果只是 PCIe Gen4 的互联那跨卡通信带宽会差一个数量级做 TP 时要格外谨慎。还有一种常见情况机器有多张卡但插在不同 PCIe switch 下跨 switch 通信带宽不稳定性能波动很大。驱动和 CUDA 版本也要统一。我遇到过两次很坑的事一次是系统里 CUDA 版本和 PyTorch 编译时用的版本不一致导致多卡初始化直接报错另一次是两块卡驱动版本不同进了推理框架后一块卡能识别、另一块卡报错。多卡环境下驱动尽量跟系统镜像走我一般用官方 PyTorch 镜像并锁定 CUDA 版本避免后续环境漂移。驱动装完后一定要用 nvidia-smi 确认两张卡的 Driver Version 一致再跑一个小矩阵乘验证 P2P 通信是否正常python -c import torch; xtorch.randn(1024,1024).cuda(); ytorch.randn(1024,1024).cuda(); print(torch.matmul(x,y).sum())如果这一步能稳定跑出结果环境基本没问题。4.2 张量并行启动配置vLLM 示例以 vLLM 为例双卡 TP 的启动命令很简单vllm serve Qwen2.5-13B-Instruct \ --tensor-parallel-size 2 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192这里我建议关注几个参数--tensor-parallel-size 是并行度--gpu-memory-utilization 控制显存使用比例--max-model-len 控制上下文上限。如果只是本地测试可以把 max-model-len 调小一点加快加载速度。上线前我用一个很小的脚本做冒烟测试确认两个 GPU 的利用率都在合理范围nvidia-smi 里看 Volatile GPU-Util而不是只在一张卡上运行。如果发现只有一张卡在动大概率是环境或者并行度设置有问题。4.3 数据并行部署实例拆分的几种姿势如果是 DP 方案操作上也并不复杂。比较常见的是用 vLLM 在多张卡上分别启动独立实例然后在前面架一个负载均衡。启动时可以通过 CUDA_VISIBLE_DEVICES 控制每张卡只跑一个实例CUDA_VISIBLE_DEVICES0 vllm serve Qwen2.5-7B-Instruct --port 8000 CUDA_VISIBLE_DEVICES1 vllm serve Qwen2.5-7B-Instruct --port 8001 然后在 Nginx 里配一个 upstream轮询这两个端口。这样做的优点是无状态、扩展性好后续如果并发量继续涨加卡加实例就行不需要动模型和代码。要注意的是各实例的并发参数max-num-seqs要一致否则集群里某些实例可能被压满另一些却闲着。4.4 上线前的压测和验收别拿直觉当结论很多团队上了多卡之后完全没有做系统的性能验收只是“感觉好像快了”。这是不对的。我强烈建议把压测跑到量化级别至少记录四个指标吞吐requests/min 或 tokens/s、TTFT首 token 延迟、TPOT每 token 生成延迟、以及错误率OOM/超时比例。压测工具上如果接口是 OpenAI 兼容格式直接写脚本并发请求即可。我常用的思路是准备一批固定 prompt设置不同并发数10、20、50、100每种并发跑 5 分钟记录上述指标。然后对比单卡基线。关键判断标准如下吞吐是否随卡数近似线性增长。TP2 能到 1.5~1.8 倍就算正常DP2 如果能到 1.8~2 倍就很理想。TTFT 是否显著下降。如果 TTFT 没有变化说明瓶颈不在模型计算而在调度或网络层。TPOT 是否下降但没翻车。TP 理论上能降低单 token 生成时间但如果通信开销过大TPOT 反而可能上升这就是方案选错的信号。我做双卡 TP 时压测结果如果 TPOT 比单卡还高了哪怕 10%就会立刻停下来查 NCCL 通信和拓扑而不是硬着头皮上线。这也是一个很重要的实战经验多卡项目上线前一定要留出足够的压测和调优时间别赶在周五晚上临时切换出了问题你连补救的机会都没有。4.5 经济账自购还是租 GPU先算清楚再决定多 GPU 不只是技术选择也是成本决策。我的经验是如果业务增速不确定或者只是短期活动需要大并发优先考虑按需租用 GPU如果业务是持续稳定增长、7×24 小时运行自购或者长租包月才更划算。这里给一个粗略的 TCO 计算思路把硬件成本一次性购买或者按月摊销、功耗成本每块卡 300W~450W 再乘以电价、机房机位成本、运维人时成本全部加进去然后除以预计承载的每千次请求数得出单次请求成本。用这个口径去对比租用方案结论会比你“凭感觉买卡”理性得多。现实中很多团队买了两张卡之后利用率不到 30%再算上折旧比租用贵了不知道多少倍。GPU 是很贵的资源按需给它负载而不是让负载去迎合硬件。5. 多卡推理的常见坑与排查记录多卡部署上线后真正折磨人的往往是那些看不到的隐性问题。我把自己这几年踩过的坑和排查思路整理出来希望能帮你省掉一些排查时间。每个问题我都按照“现象 → 可能原因 → 排查方法 → 解决思路”来写。5.1 上了 TP 但吞吐反而下降通信开销大于计算收益这是最崩溃的场景之一明明从 1 张卡升到了 2 张卡压测发现吞吐不仅没涨反而掉了 10%~20%。第一反应先看 nvidia-smi topo -m确认卡间是不是直连 NVLink。如果不是而是走了 PCIe 甚至是跨 CPU socket那 TP 的 all-reduce 通信延迟会抵消掉并行计算收益这时候只能放弃 TP 转 DP。还有一个隐蔽问题如果模型本身很小比如 7B一张 A100 已经完全能扛住计算你再上 TP2纯属增加通信开销。这种情况下TP 都是负优化DP 才是正解。我的判断准则很简单单卡显存能装下的模型默认不做 TP只有装不下了再考虑 TP。5.2 DP 实例负载不均部分卡打满、部分卡闲着数据并行经常出现一种现象两张卡一张 GPU 利用率 95%另一张 40%总吞吐却没什么改善。这个问题大多出在负载均衡策略上。如果用的是轮询短请求和长请求被打到不同卡上就会出现“一张卡已经处理完一批短请求另一张卡还在死磕两个长请求”的情况。对策分两层。第一层负载均衡层改用 least_conn 算法让新请求进到当前活跃连接数最少的实例第二层如果请求长短差异太大考虑在业务层做超时控制或者给长请求单独一条链路。另一个很常见的坑是不同实例的并发参数不一致导致某些实例在 max-num-seqs 之外排队某些实例还能轻松接收请求。统一参数是基本操作。5.3 显存 OOM 出现在多卡环境下先区分是哪个模块吃掉的多卡部署后出现 OOM比单卡时更难排查因为你得知道是权重切分后没放平还是 KV Cache 预留不足。我的排查顺序是先看错误日志里是否报 NCCL、CUDA OOM 还是 PyTorch OOM然后用 nvidia-smi 看各卡显存占用是否均衡如果某一张卡明显偏高大概率是并行切分不均或者有额外的 buffer 在这张卡上。一种容易被忽略的情况TP 下 KV Cache 也是被切分到多卡的但不同卡上剩余显存可能不同导致某张卡先爆。解决办法是把 gpu-memory-utilization 调低一些留出约 5%~10% 的余量同时限制 max-num-seqs别让 vLLM 的调度器把显存排满。排得太满像内存碎片一样偶发性 OOM 会非常难查。5.4 GPU 驱动崩溃、crash dump多卡放大了单点风险多卡环境下单张卡的硬件或驱动稳定性问题会被放大因为一张卡出问题可能导致整个 TP 组不可用。我遇到过 GPU crash dump triggered 的报错表现是某张卡突然掉线日志里带一堆 GPU 相关的 dump 信息服务整体卡死。这种问题多数是驱动不稳定、卡间通信异常或者过热引起。排查思路先看 dmesg 和 /var/log/messages 里有没有对应时间点的硬件错误再用 nvidia-smi -q 查每张卡的温度、功耗、PCIe 链路状态如果只是偶发考虑升级或回退到更稳定的驱动版本。多卡集群还要加一层健康检查定期拉取每张卡的运行状态一旦发现卡掉线能自动把流量切到备用组而不是等服务完全不可用后再人工介入。5.5 常见问题速查表现象可能原因排查路径解决思路TP 后吞吐不升反降卡间通信带宽不足或模型太小nvidia-smi topo -m压测对比换 DP或保证 NVLink 环境多卡负载不均负载均衡策略失效、并发参数不一致检查各实例队列数、Nginx 连接数改 least_conn、统一参数多卡后偶发 OOMKV Cache 预留过多、显存碎片看各卡显存占用、vLLM 日志调低 gpu-memory-utilization、限制 max-num-seqs某张卡 crash dump驱动不稳定、过热、硬件故障dmesg、nvidia-smi -q更新驱动、加强散热、加健康检查启动时只有一张卡工作CUDA_VISIBLE_DEVICES 设置错、并行度参数没生效打印 torch.cuda.device_count()检查环境变量和启动参数多卡管理的复杂度是成倍上升的不只是多一张卡的问题还涉及通信、调度、故障隔离、成本控制。我的经验是上多卡之前先问自己一句“单卡优化真的做到头了吗”如果没有先把单卡榨干如果确实做到了头再按文中的判断标准去选路线然后严格跑压测验收。每一步都稳一点比最后手忙脚乱救火要省心得多。

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

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

免费获取报价