首页 / 资讯中心 / 文章详情

GPU利用率低?异构算力池化与智能调度实战解析

GPU利用率低?异构算力池化与智能调度实战解析 ★ FEATURED ARTICLE
聊个实际问题我见过不少企业的 GPU 集群监控面板上的利用率常年只有 30%~50%但业务方天天喊卡新任务排队等卡底层却有大把算力在空转。这种局面通常不是显卡不够而是算力没被好好调度起来尤其是当集群里还混着 A100、4090、国产加速卡的时候情况会更乱。GPU 利用率提升 1.3 倍听起来像营销话术但如果你真的把训练、微调、推理任务混部到同一批异构 GPU 上并且把显存、算力粒度切分到合理水平这个数字完全能达到。我最近在整理 ZStack AIOS 这类智算操作系统的落地经验核心就一句话把异构算力当成一个可调度的池子而不是一台台孤立的物理机。这篇文章就围绕这句话展开讲清楚 GPU 利用率为什么低、异构算力怎么池化、具体调度怎么操作、监控排障怎么做适合正在折腾 GPU 集群、被利用率折磨的运维和平台工程师参考。1. 先聊清楚GPU 利用率低下的病根在哪1.1 单卡利用率低采集指标与真实水位很多团队说“利用率低”其实是用错了指标。nvidia-smi看到的 GPU-Util 是采样瞬间 SM流处理器的忙碌比例它不代表真实吞吐。我用一个例子解释一个推理服务每个请求只有 200ms其中 GPU 计算只占 50ms剩下 150ms 在等数据从 CPU 侧拷贝、等 Python 做预处理和后处理。这个服务跑满 100 QPS 时nvidia-smi可能只显示 30%~40%因为 GPU 总是在“等活儿”。此时就算把利用率数字刷上去QPS 也上不去因为瓶颈在数据传输和预处理不在计算本身。真正的利用率要看三件事SM 占用率SM Occupancy、显存带宽利用率、以及端到端吞吐。SM 占用率决定计算单元有没有被塞满显存带宽决定访存密集任务有没有卡在 HBM 上。很多运维只看 GPU-Util忽视了帧缓冲显存使用——显存快满了但 SM 空闲这种状态下任务不排队才怪。另外单卡利用率低往往是因为并发不够。比如微调一个 7B 模型batch size 设成 1一张 A100 哪怕满速跑SM 占用率也上不去把 batch size 凑到合适区间把 TensorCore 喂饱吞吐能翻番。这就是为什么做 GPU 利用率优化时第一步不是调调度器而是先看模型服务的请求并发和 batch 策略。这块不解决调度层面怎么切分都是白搭。1.2 传统虚拟化在异构算力面前的尴尬传统私有云那套 VM 思路碰到 GPU 特别别扭。原因有几点GPU 设备不能像 CPU 那样轻易超卖。CPU 可以配 oversubscription因为任务多数时间在等待GPU 是计算密集设备超卖后直接表现为显存溢出或任务相互拖慢。PCIe 设备直通PCI Passthrough虽然性能好但一台机器最多直通给少量虚拟机而且 VM 不感知 GPU 拓扑无法做 NUMA/GPU 亲和调度。传统虚拟化缺少“算力分组”概念想给两个训练任务各分配 50% 的 A100 算力如果不做 MIG 或 vGPU基本做不到。更麻烦的是异构。数据中心里往往有 A100、A800、4090、3090还有国产加速卡。不同卡的显存大小、算力规格、驱动接口都不一样。传统平台只能按“机器 设备”粒度分配用户申请一张卡调度器只能找一张空闲卡塞进去完全不管这张卡是否满足任务真实需求。结果是重计算任务被分到弱卡上跑不动轻任务占了强卡浪费资源。1.3 ZStack AIOS 解决什么问题ZStack AIOS 这类智算操作系统本质是把 GPU、NPU、异构加速卡当成数据中心级资源来管理而不是虚拟机附属设备。它在平台层做四件事异构设备统一纳管、资源池化与细粒度切分、基于真实负载的调度、以及多集群统一监控。我特别想强调“细粒度切分”这点。比如一张 80G 显存的卡训练任务需要 40G推理任务需要 20G另外 20G 可以切给一个轻量服务。平台通过显存隔离和算力限额让三拨任务互不干扰地跑在同一张卡上。这种能力直接改变了利用率下限原来一张卡只能跑一个任务现在可以跑两到三个。标题里说的 1.3 倍在这种场景下非常现实。要注意细粒度切分不是简单的“显存瓜分”。算力份额、显存隔离、显存带宽争用都要考虑。如果只做显存隔离不做算力隔离两个任务互相抢 SM最终谁都没跑快。ZStack AIOS 的调度策略支持按显存、按算力、按卡三种粒度实际部署时我建议优先用“显存 算力”组合。2. 异构算力池化从硬件异构到统一调度2.1 异构算力到底指什么异构算力这个词常被滥用。在数据中心场景它至少包含三层含义芯片架构异构NVIDIA GPU、AMD GPU、国产 GPU/NPU、甚至 CPU 的向量指令集。指令集不同编程模型也不同CUDA、ROCm、CANN 各自为政。产品型号异构同品牌不同代际比如 A100 与 L40S显存大小、NVLink 能力、TensorCore 代际都不一样。使用方式异构同一张卡可以跑训练、微调、推理、渲染这些工作负载对资源的需求特征完全不同。异构带来的最大问题是“不可替换性”。CUDA 任务无法直接跑到 ROCm 上NPU 任务更挑算子适配。所以异构池化的第一步不是“统一到抽象层”而是“资源打标签 声明式调度”。也就是说每张卡都标注好架构、型号、驱动版本、剩余显存、当前算力份额任务在提交时声明“我需要什么卡、多大显存、多少算力”调度器再匹配。这一步不做好后面所有优化都无从谈起。2.2 设备插件与 GPU 直通/虚拟化的取舍在 Kubernetes 体系里调用 GPU 的标准方式是 device plugin。ZStack AIOS 底层支持标准 Kubernetes 生态这也意味着很多 K8s 上成熟的 GPU 调度实践可以直接复用。具体来说有三种常见的接入方式直通模式Passthrough把整张 GPU 映射给一个容器性能最好但粒度最粗一张卡只能给一个任务。适合少数独占场景比如需要多卡通信的模型并行训练。虚拟化模式vGPU / MIG把一张物理卡切成多个逻辑卡支持显存和算力隔离。MIG 是 NVIDIA 官方方案但只支持部分新卡vGPU 依赖 NVIDIA vGPU 授权国产卡各有各的切分方案。ZStack AIOS 这类产品会做兼容封装让用户通过统一界面申请“2G 显存 20% 算力”这样的资源。显存共享模式如 CUDA MPS、池化技术不切分物理设备但通过进程级调度限制算力。MPS 适合把多个小推理任务塞进同一张卡但要小心显存隔离缺失的问题——如果某个任务申请了过多显存其他任务会被 OOM 牵连。我的建议是训练任务尽量用直通或多卡绑定的方式推理任务和开发调试用 vGPU 或显存共享。全用直通利用率很难提上去全用 vGPU训练性能又可能打折。混合使用才是正解。2.3 一张表看懂常见调度策略这里把我常用的调度策略整理成了表格方便对照策略粒度适用场景注意事项整卡独占1 张物理卡大模型预训练、多机多卡并行利用率低但稳定MIG / vGPU 切分1/7、1/4 等逻辑卡中小推理服务、开发环境需授权算子兼容性要测显存共享进程级batch 推理、小请求高并发必须有 cgroup/算力限额算力限额按计算资源百分比混合部署、离线在线混部与显存隔离配合使用抢占式调度队列级多个团队共享集群需要 checkpoint否则任务被 kill 损失大我不建议一上来就追求“全集群自动最优调度”。更靠谱的路径是先用整卡独占跑通业务再逐步放开 MIG/显存共享最后再上抢占式。每一步都做容量评估避免为了利用率数字牺牲稳定性。毕竟调度器再聪明也扛不住业务自身不配合。3. 实操怎么把利用率从 60% 拉到 80%3.1 起步摸清家底和真实负载想提升利用率先把集群的真实情况摸清楚。我通常会做一周的基线采集记录每个节点每小时的平均 GPU-Util、显存使用量、SM 占用率、任务数量、排队时间。这里有个技巧不要只看平均要看 P95。平均利用率 60% 可能意味着高峰 90%、低谷 30%调度器需要在高峰时把任务错峰而不是无脑扩容。采集工具方面DCGMNVIDIA Data Center GPU Manager是首选能拿到 SM 占用率、温度、功耗、显存带宽等细粒度指标。配合 Prometheus Grafana 做监控大盘能直观看到任务对资源的真实占用。我见过一个客户报表说资源利用率 55%实际打开 Grafana 一看白天开发环境的 Jupyter Notebook 占了 60% 的显存但 SM 占用几乎为 0。这就是典型“显存放着不用”的场景。解决办法不是买新卡而是给开发环境设置 idle 超时回收比如 2 小时无操作自动释放资源顺便把 GPU 共享权限收回让开发人员按需申请而不是常驻占用。3.2 任务调度策略显存切分、算力限额与分布式排队摸清基线后就可以按资源需求把任务分类。我建议分成三类重训练任务需要整卡或多卡、轻训练/微调任务显存小于 40G、算力需求中、推理任务高并发、低延迟、显存需求多样。然后在 ZStack AIOS 里配置资源模板。比如给微调任务配置“20G 显存 30% 算力”的模板多个微调任务可以共享一张 A100但算力总量限制在 80% 以下留出余量给推理任务应对突发流量。给推理任务配置“显存按需 算力上限 50%”的模板推理服务本身有弹性允许被调度器抢占配合 HPA 实现副本伸缩。给开发环境配置“低优先级 idle 回收”策略避免资源被长期占用。调度策略上我强烈建议开启集群级分布式排队。很多平台只做单节点调度如果一个节点没卡了任务就在那等着哪怕其他节点有空卡。分布式排队会把全局空闲资源统一调度任务等待时间可以从小时级降到分钟级。ZStack AIOS 的调度器我实际观察下来在几百卡规模下重新调度一个失败任务只需要秒级。需要注意的是队列优先级要配合业务方梳理。不能简单按提交时间先来先服务而要考虑任务紧急程度和预估时长。我的做法是让每个训练任务提交时声明预计时长调度器在排队空隙插入短任务把碎片时间利用起来。这个机制对提升集群整体吞吐特别有效。3.3 推理场景优化动态批处理与显存复用推理场景是利用率提升的最大突破口。很多人部署了大模型推理服务比如用 vLLM 部署 Qwen 或 FunASR 语音识别然后盯着 GPU-Util 只有 20% 发愁。其实问题往往在动态批处理continuous batching没有配好。vLLM 这类框架原生支持 continuous batching它的核心思想是不再等请求凑够一个 batch 才开始推理而是每生成一个 token 就把新请求插入到当前 batch 的空闲位置。这样 GPU 的利用率会大幅提升。我在实际部署时会把max_num_batched_tokens调大并开启抢占式调度让长序列请求主动让位给短序列请求减少排队阻塞。还有个容易被忽视的点显存复用。推理服务分配 KV cache 时往往会预留大量显存。如果平台没有做显存复用每个副本都预留整卡显存那 GPU 利用率不可能高。正确做法是让推理服务根据实际流量动态扩容副本但共享同一块显存池。ZStack AIOS 支持显存池化这一点在部署推理服务时非常有用不需要每个 Pod 独占整卡显存而是按需分配 KV cache 大小。我在部署 FunASR 的时候踩过一个坑默认参数下它只用一个 batchGPU-Util 只有 15%。调大 batch size、开启流式处理之后利用率直接到 60% 以上。所以遇到推理任务利用率低先别怪平台先看框架的 batching 配置。3.4 让模型训练/微调和推理共享集群最理想的状态是训练、微调、推理三个类型的任务跑在同一批 GPU 上。但混部不是把任务都丢进去就行需要做好资源隔离和优先级。我的典型配置是用 vGPU 切分出 70% 算力给训练任务剩余 30% 给推理任务。训练任务可以抢占推理任务但会提前 5 分钟通知让推理服务优雅退出。这里的关键是 checkpoint 机制。如果训练任务没有定期保存权重一旦被抢占整天的计算就白费了。所以在混部前必须先保证所有训练任务 30 分钟自动 checkpoint 一次。还要强调一点监控混部集群时不能只看单个指标。如果显存分配率已经 90%但 SM 占用只有 40%说明显存不够而算力富余需要调整任务切分比例。如果反过来SM 占用 90% 但显存只用 50%说明算力不够需要限制并发任务数。我做扩容评估时会把这两组指标画成散点图观察资源瓶颈在哪。这个可视化的过程比任何调参都管用。也不要迷信 100% 利用率好的运行状态是“每个任务都能及时拿到资源整体利用率维持在 70%~85%”。如果你能把集群稳定维持在这个区间恭喜你已经跑赢了大多数团队。4. 监控排障别等业务挂了才看曲线4.1 关键监控指标与告警阈值GPU 集群监控和 CPU 集群有很大区别最明显的是故障模式不同。CPU 挂了通常是性能下降GPU 挂了经常是显存 ECC 错误、驱动重置、温度过高直接影响任务稳定性。我建议至少盯住这几个指标指标含义建议告警阈值GPU-Util当前流处理器利用率P95 持续低于 20% 时关注SM OccupancySM 实际占用程度低于 30% 时检查 batch 配置显存使用率已分配显存 / 总量超过 90% 告警GPU 温度器件温度达到 80℃ 告警ECC 错误显存纠错事件出现单次即告警功耗使用功耗 / TDP持续低于 30% 可能是任务没喂饱DCGM 健康状态驱动、NVLink、PCIe 链路非健康即告警这里有个经验GPU-Util 高不一定代表健康。如果显存使用率同时很高、SM Occupancy 也高说明任务在认真跑。如果 GPU-Util 冲到 99%但显存使用率很低很可能是任务在读显存时反复等待实际是显存带宽瓶颈要检查访问模式。告警通道上我用的是 Prometheus Alertmanager 推到企业微信和飞书。告警规则要区分“节点硬件告警”和“业务性能告警”硬件告警看 ECC、温度、驱动错误性能告警看任务的排队时长和利用率水位。很多人把这两类混在一起结果夜里被无用告警轰炸反而忽略了真正的硬件故障。4.2 常见问题与排查速查表根据我接触过的集群把高频问题整理成了速查表供各位直接抄作业现象可能原因排查方向任务一直 Pending节点资源不足 / 标签不匹配看调度器日志检查卡标签和资源模板GPU-Util 很低batch 太小 / 数据加载慢看框架配置与数据管道多任务抢占后卡死checkpoint 周期过长缩短 checkpoint 间隔增加优雅退出机制容器内torch.cuda.is_available()返回 False镜像内 CUDA 版本与驱动不匹配检查容器基础镜像重装 PyTorch GPU 版显存 OOM显存切分过细 / 任务峰值超申请调整 vGPU 显存大小记录峰值用量性能忽高忽低其他任务的算力抢占开启算力限额限制最高占用温度告警机柜散热不足 / 高负载长时间运行调整温控策略或错峰调度任务驱动重置硬件故障 / VFIO 冲突查看 dmesg重启后观察是否复现排查这类问题我有个基本顺序先看监控曲线判断是资源瓶颈还是程序问题再进容器看nvidia-smi和进程状态之后看调度器日志和事件最后再看业务日志。千万别一上来就盯业务代码很多时候是资源模板没写对。还有个容易翻车的地方某些国产卡的驱动和监控工具不是nvidia-smi。过去很多团队用统一的脚本采集结果对不上。ZStack AIOS 这类平台会自动识别不同品牌卡的监控接口统一成一套指标省去很多适配工作。如果你的环境是自己写的脚本记得把接口差异考虑进去。4.3 我们踩过的三个坑第一个坑是盲目开 MIG。当时为了提升利用率给 A100 开了 7 个 MIG 实例把一张卡切成 7 份跑推理。结果有些算子在小算力切片上性能衰减严重尤其是 attention 类算子最终整体吞吐反而下降了。后来我们把算法任务和推理任务分开算法任务用整卡推理任务用大切片比如 1/2 卡效果立刻好转。第二个坑是没做显存限额就开共享。某次为了“充分利用显存”让多个推理任务共享一张 80G 卡结果其中一个任务显存泄漏把整张卡占满其他任务全部 OOM。从那以后我坚持共享必须配显存硬限额宁可让任务显存申请排队也不能让一个任务拖垮整卡。第三个坑是训练任务 checkpoint 间隔太长。集群做了抢占式调度后低优先级任务随时可能被高优先级任务挤掉。当时有个微调任务每 4 小时才存一次权重结果连续两次被抢占重跑了好几轮。后来统一把 checkpoint 间隔改到 20 分钟配合分布式文件系统存储损失控制在几分钟内。混部的前提是有完善的 checkpoint 机制没有这个别谈抢占。5. 选型与落地的几条实在建议5.1 怎么评估一个智算操作系统如果你也在评估 ZStack AIOS 或者同类产品我建议从四个维度做验证异构纳管能力是否能把多品牌、多型号的加速卡统一纳管国产卡的驱动适配做到什么程度不要只看宣传要拿实际卡去测试。切分粒度显存、算力、整卡三种粒度是否都支持切分后的性能损耗是多少特别是 MIG 或 vGPU 下的算子兼容性。调度策略是否支持优先级、抢占、分布式排队调度器在几百卡规模下的调度耗时是多少是否有防碎片机制可观测性能否统一采集所有卡的监控指标告警是否可配置日志和链路追踪是否齐全这三个维度缺一不可。我见过有团队只看“能不能调度 GPU”忽略了切分和监控结果用起来非常痛苦。从长期看可观测性甚至比调度本身更重要因为你要靠数据持续调优。5.2 优先落地路径先盘活存量再谈扩容很多企业一上来就想买新卡我觉得这是误区。GPU 利用率低的问题多数靠“整理存量”就能解决一大半。我建议按这个顺序推进先做一周基线采集摸清真实利用率和瓶颈。给所有任务打标签明确资源需求。把开发环境和测试环境先切到 vGPU/共享模式释放空闲显存。再把推理服务调优 batching提高单卡吞吐。最后再考虑训练/推理混部引入抢占式调度。每走一步都要量化对比用了多少卡、跑了多少任务、排队时间缩短多少、利用率提升了多少。等存量盘活了如果还不够再考虑扩容这样扩出来的每张卡都能发挥价值。5.3 需要避开的隐性成本这里说几个常被忽略的成本授权成本NVIDIA vGPU 需要授权MIG 在某些卡上也有功能限制采购前要算清楚。适配成本国产卡的算子库、框架兼容性参差不齐迁移一个模型可能要多花几周。选平台时尽量选适配做得全的。运维成本GPU 故障率比 CPU 高ECC 错误、驱动重置、散热问题都需要专门的监控和响应流程。人员成本调度策略、资源模板、监控告警都需要人维护别指望部署完就什么都不管。把这些成本算进去你会发现一个好的智算操作系统省下的不只是硬件钱还有大量运维人力。这也是为什么我倾向于推荐成熟平台而不是自己从头写脚本的原因。最后再分享一个我自己反复验证过的经验GPU 利用率优化不是一个一次性项目它更像一个持续调优的过程。每次业务模型升级、框架版本更新都值得重新审视资源模板和监控水位。能稳定把利用率维持在 70% 以上的团队已经能体现出明显的成本节省。很多时候问题真不是卡不够而是卡没被用对地方。希望这篇实战记录能让你少走几步弯路。
阅读完成 · 觉得有帮助?
咨询建站