算力不够还是没组织好?GPU资源调度与利用率优化实践
2026/9/4 23:52:28 网站建设 项目流程

做人工智能平台和算法基础设施有一段时间的人,多半见过这种场面:早上训练任务排队,晚上集群里一堆 GPU 的空闲率超过一半;算法同学在群里说抢不到卡,运维同学把监控截图贴出来,发现 24 小时平均利用率还不到 30%。一卡难求和算力闲置并存,表面看是供需矛盾,本质其实是同一个问题:算力没有被很好地组织起来。

这里说的“组织”,不是统一采购或者强制共享那么简单,而是把分散的 GPU 变成可申请、可调度、可计量、可回收的资源。适合看这篇文章的人,是算法工程师、后台工程师、技术管理者,以及准备把训练、推理和日常开发任务放到同一批机器上管理的团队。AI 下半场,大量真实消耗正在从训练扩散到推理和应用调用,token、Agent、AI 编程这类场景的峰值波动越来越明显,算力的组织方式往往会比显卡数量更早成为瓶颈。

下面按我的实际理解拆一遍:先判断问题在哪一层,再讲清楚怎么拆资源、怎么选路线、怎么落地、怎么看效果、怎么排查。

1. 算力不够,还是算力没有被组织起来

1.1 缺的不一定是总量,而是“匹配任务的算力形态”

大模型训练、模型微调、批量推理、在线推理、实验调试,这几类任务对算力的要求完全不一样。

大模型训练需要高显存、多卡并行、卡间高速通信,最好是整批同规格机器;批量推理可以接受排队,关键是吞吐稳定;在线推理要求低延迟,任务来了就得响应;实验调试只想要一两张卡快速跑通,不关心集群拓扑。

很多团队说算力不够,其实不是总卡数不够,而是“能匹配任务的形态不够”。比如某个微调任务只需要 1 到 2 张卡,却被固定绑定在一台 8 卡服务器上;任务占着整机,其他 6 张卡在大部分时间里空转。等真正需要 8 卡并行的大训练任务进来,这台机器又腾不干净。这种错配在中小团队里非常常见。

所以判断第一步,不要先看 GPU 总数量,而是把任务清单拉出来:哪些任务需要整机多卡,哪些任务单卡就够,哪些任务只需要半卡或临时碎片资源。分类之后,很多“不够”会变成“分不匀”。

1.2 先到先得、手动挑卡,是闲置的第一来源

我见过不少团队用共享服务器的方式管理 GPU:每个人都 SSH 登录机器,先执行 nvidia-smi 看还有没有卡,然后自己设 CUDA_VISIBLE_DEVICES,把任务挂到某个空闲卡上。

这种模式有几个硬伤。

第一,先到先得。谁先占卡谁赢,任务等级、业务重要性、截止时间都不参与决策。早上一批低优先级任务把卡占满,下午真正要上线的推理服务反而进不来。

第二,任务退出不主动释放。部分进程因为显存不足、OOM 或者代码异常退出后,GPU 进程没有清理干净,卡在监控里一直显示被占用。遇到这种情况,用户只能自己再去 kill,体验很差。

第三,夜间和周末基本靠自觉。没有人回收空闲资源,也没有人能把临时不用的卡转给下一个人。白天排不上、晚上没人用,就这样长期共存。

手动管理模式在三四张卡的时候还能忍受,一旦机器超过十台、使用者超过五个人,就需要引入队列、配额和回收规则。

1.3 部门之间的资源墙,本质是缺少“共享治理”

还有一个容易被忽视的层面:部门墙。

团队 A 为了赶项目,按业务峰值申请了一批 GPU,平时利用并不高;团队 B 临时要做评测,申请预算却要等几个月。两边都想减少不确定性,最后结果就是每个团队都按自己的峰值囤卡,资源在整体上看就是一边紧缺,一边闲置。

部门之间不敢共享,通常不是技术问题,而是治理问题:没有配额,怕别人抢占;没有计量,算不清成本;没有隔离,担心任务互相干扰;没有观测,卡被谁用了都看不到。

所以“谁来组织算力”这个问题,答案不是某一个人,而是需要一小批平台或基础设施工程师,同时配上一套可执行的资源规则。只上工具不上规则,工具很快会变成新的争执点。

2. 重新组织算力,先拆清资源、调度、平台三层

2.1 资源层:把物理卡变成可描述、可切分的资源

算力组织的第一步,是让机器能准确描述“自己有多少资源”。

GPU 和 CPU 不一样,不能只看总量。一张卡包含计算单元、显存、带宽、功耗等多维属性。调度系统要能知道某个节点有几张卡,每张卡还有多少显存,当前计算负载高不高,这样才能决定把任务放到哪里。

如果要做更细的资源切分,常见思路是引入 GPU 共享或虚拟化机制,把一张卡切成多个更小的逻辑资源;在容器化环境里,通常通过设备插件或资源上报机制,让调度器感知卡数和显存大小。

这里最容易被误解的是:显存够用不等于算力够用。两个任务同时放在一张卡上,只要显存没爆,系统就认为没问题,但两个任务都在密集计算时会互相拖慢,各自的完成时间都会明显拉长。所以资源层要同时关注显存和算力,不能只看一个维度。

2.2 调度层:任务不是塞进去,而是排好队、能打断、能恢复

调度层解决的核心问题是:当请求大于供给时,谁先跑、谁后跑、谁可以让路。

常见机制包括队列、优先级、公平份额、抢占。队列用来区分任务类型,训练队列和推理队列不应该混在一起;优先级用来告诉调度器哪些任务可以先跑;公平份额保证某个团队不能无限占用公共资源;抢占则是当高优先级任务到达时,让低优先级任务让出资源。

这里要多说一句:抢占不能乱用。如果被抢的任务没有及时保存中间结果,强杀之后下次又要从头开始,反而浪费更多算力。更稳的做法是给可抢占任务开启周期性 checkpoint,让调度器在收回资源之前先给任务一个保存现场的机会。

任务超时回收同样重要。很多任务挂在那里既不报错也不退出,很可能是在等一个永远不会来的锁,或者代码里有个死循环。给任务设置合理的最大运行时间,超时自动结束并把资源释放回池子,是避免“占着茅坑不跑路”的关键手段。

2.3 平台层:配额、成本、观测决定能不能长期运转

调度器负责做分配决策,平台层负责让规则可执行、可监督。

具体来说要做三件事。

一是配额管理。每个团队、每个项目能同时使用多少卡、多少内存,应该有明确上限。配额不是用来卡人,而是让资源有可预期的边界。

二是成本计量。至少要把“显卡时数”记录下来,也就是某个任务从开始到结束用了多少张卡、多少个小时。没有计量就没有成本意识,使用者会倾向于写一个大资源请求占着不放。

三是观测。要能看到任务排队时间、运行状态、资源占用、失败原因。用户信任调度系统,前提是系统能回答“我的任务现在在哪里、为什么还没跑、卡被谁占了”。

平台层做得再简单,也要先把配额和观测补齐,否则规则只能停留在口头上。

3. 从单机到集群:三套技术路线,怎么选

3.1 重型训练和科学计算:传统调度器适合稳定队列

如果你的场景以多机多卡训练、科学计算为主,任务生命周期比较长,用户习惯通过命令行提交作业,那传统调度器仍然是非常稳的选择。

以常见的 Slurm 为例,用户提交任务的方式很直接:

srun --gpus=1 --time=02:00:00 python train.py

这类调度器在排队、优先级、资源分配上已经很成熟,适合任务形态固定的团队。缺点是容器化、日志、服务发现等能力相对薄弱,如果任务需要频繁启停,或者要和微服务体系打通,需要额外做很多适配。

3.2 应用化、多团队共享:容器调度生态更贴近现代开发

如果团队里有训练、推理、数据预处理、在线服务多种任务,需要多租户隔离、镜像管理、日志采集,那 Kubernetes 生态会更合适。

常见的做法是:用 Kubernetes 管理节点和容器,通过设备插件上报 GPU 资源,再引入调度增强能力来处理队列、优先级和配额。项目空间、资源限额、容器日志这些能力都是现成的,对已经熟悉云原生开发的团队来说上手成本更低。

容易踩的坑是:Kubernetes 原生调度逻辑不会主动识别 GPU 拓扑、显存大小与多机通信需求,直接把训练任务当普通容器调度,可能出现跨机通信链路过长、任务等待资源碎片等问题。很多团队会在上层增加排队插件、拓扑感知或任务级调度器来做补偿。

3.3 分布式 Python 任务:任务编排框架适合灵活场景

如果你的算力组织更多面向 Python 生态,比如用 Ray 或类似框架跑数据并行、参数搜索、批量推理,可以考虑在这一层做任务编排。

它们的优势是任务提交更灵活,能直接处理函数级和 Actor 级调度,失败任务可以重试,资源也能根据任务动态申请。缺点是它更偏计算框架,不太关心多租户配额和部门成本分摊,适合作为平台的一部分,而不是平台本身。

3.4 自建、云实例、租赁:按负载生命周期判断

很多团队会纠结到底要不要自建机房,还是用云主机,还是租算力平台。我的建议是:不要按“哪家便宜”来选,先按负载生命周期来判断。

对比维度自建集群云上 GPU 实例算力租赁平台
成本结构前期采购高,后期闲置成本高按量或包年,弹性可控按时、按卡灵活
交付速度慢,涉及采购、上架、组网快,分钟级到小时级快,通常分钟级
弹性能力低,扩容周期长高,但受库存和配额影响中高,看服务商供给
数据管控完全可控依赖云厂商安全边界需要关注数据隔离和私有部署
适合场景长期稳定的大规模训练弹性测试、突发扩容、在线推理中小团队、短时任务、临时评测

如果你有长期稳定的训练负载,机器 7×24 小时基本不空,自建或包月更划算;如果负载有明显高峰低谷,应该用弹性方式补齐;如果只是偶尔试跑、评测、微调,直接租按量的资源更省心。

这里给一个通用建议:把 80% 的固定负载放在长期资源上,把 20% 的突发负载放在弹性资源上,先别追求一步到位建一个大而全的算力池。

4. 落地路径:先盘点,再试点,再定任务规范

4.1 先盘清现状,别急着上平台

我见过最典型的失败案例,是资源管理混乱的团队直接引入一套重型算力平台,结果所有人都不会用,任务提交门槛反而变高。

更稳的做法是先盘点。至少回答这几个问题:一共有多少张卡,分布在哪些机器上;每个用户或团队实际在用多少;一周内白班、夜班、周末的利用率分别是什么水平;有哪些任务长期占卡但产出很低;哪些任务经常排队且时间敏感。

盘点工具不需要很复杂。基础命令可以看当前状态:

nvidia-smi

但 nvidia-smi 只能看到当前时间点,要判断“一段时间内是否空闲”,需要把 GPU 的显存使用率、算力利用率、功耗和进程信息持续采集下来。如果暂时没有监控系统,可以先人工记录一周,再决定要不要投入做平台。

4.2 先定义最基础的任务规范

算力要组织起来,任务不能是“我随便跑一下”的状态。任务至少需要声明几类信息:申请多少卡、多少内存、预计跑多久、属于什么优先级、失败后要不要自动重试。

下面是一个很简化的示例配置,具体字段要以你使用的调度平台为准:

# 示例配置:按实际平台调整 queue: default # 队列:default / inference / high_perf priority: medium # 优先级:low / medium / high resources: gpu: 1 # 申请 1 张 GPU memory: 16Gi # 申请 16G 内存 timeout: 4h # 超过 4 小时自动回收 restartPolicy: OnFailure # 失败后自动重试

为什么要这样严格要求?因为调度器只能根据任务声明做决策。如果每个人都写“给我 8 张卡保险一点”,调度器会认为整机都被占满,后续任务全部排在队尾,而实际任务可能只用了一张卡。资源声明越诚实,调度效率越高。

4.3 试点范围控制在两三个团队之内

资源管理最大的阻力来自习惯改变。不要一开始就要求全公司、全部门切换,先找两三个愿意配合的团队,选一条有代表性的流水线做试点。

可以是“模型微调 + 离线评测”的组合,也可以是一条每天都会跑的批量推理任务。跑通之后,重点看三个数据:从任务提交到开始运行的时间是否缩短;同样一批任务的总完成时间是否变化;空闲时段有没有被利用起来。

试点阶段不要把指标定得太复杂,先看“排队时间”和“整体完成时间”。这两个指标直观,能直接反映组织效率。

4.4 先单任务,再批量,最后开放自助提交

很多团队一上来就追求全套自助服务,结果把平台做成摆设。

我更建议按顺序推进:先在少量机器、少量用户之间让任务队列跑通;再开放批量任务,让用户能看到自己的任务排队位置;最后再逐步开放给更多团队使用。

对于在线推理任务,要单独设置低延迟队列,避免训练批量任务把推理资源挤占掉。训练任务可等待,推理任务不能一直等,两类任务放在同一个默认队列里,早晚出事。

5. 判断算力组织效果,别只看一个“GPU 利用率”

5.1 算力维度:显存使用率和真实计算使用率要分开看

很多管理者只盯一个指标:GPU 显存使用率。看到显存快满,就觉得卡没白买。实际上,显存代表的是“资源有没有被分配”,不代表“计算单元有没有干活”。

一个任务可能申请了 40G 显存,但大部分时间在等数据传输、等 CPU 处理数据,GPU 的算力利用率并不高。把显存和算力分开统计之后,才能看清哪些任务属于“占着显存不计算”。

判断标准建议这样定:显存使用率用来判断是否还有空间放入更多任务;算力利用率、功耗、编码器活动和任务完成进度用来判断任务是否真的在推进。

5.2 交付维度:排队时间和任务完成时间是核心

组织算力的最终目标,是让业务任务更快拿到结果。

如果只把 GPU 利用率从 30% 提到 80%,但核心训练任务排队更久、完成时间更长,这个提升就没有意义。更有价值的指标是:高优先级任务从提交到启动的平均时间;固定批次任务从开始到全部完成的耗时;在线推理请求的延迟和成功率。

5.3 稳定维度:任务成功率和失败恢复要盯住

共享集群里最容易出现的问题是“任务跑一半被别人抢占”,以及“集群抖动导致任务挂掉”。

所以稳定维度至少要看:任务最终成功率;因为抢占或资源回收导致的中断次数;中断后能否从 checkpoint 继续;低优先级任务有没有出现饿死,也就是永远排不上。

如果抢占次数很高,但中断的任务都无法续跑,那这种组织方式就是在浪费算力,需要调整抢占策略,或者给可抢占任务加自动保存。

5.4 成本维度:从“卡时数”到“单位有效产出”

成本核算不要只看采购价,要落到“有效卡时”上。

比如同样完成一次模型微调,手动模式下可能因为排队、占卡、失败重试花了 100 个卡时;组织好之后只花了 40 个卡时。单看集群总利用率可能差别不大,但单位有效产出提升了一倍。

如果团队做 AI 应用,还可以继续细化到“每千次请求消耗多少卡时”或者“每百万 token 消耗多少算力”。把成本拆到业务单位,管理者才能判断某个新功能到底值不值得上线。

6. 卡占着、排不上、跑得慢,按这个顺序排查

6.1 先看现象,再看队列,最后才看代码

共享集群的问题排查,最忌讳一上来就怀疑算法代码。

我的习惯是固定一套顺序:

  1. 先看任务状态:是排队中、运行中、失败还是退出。
  2. 再看队列概览:当前有多少任务在排队,谁的优先级高,集群是不是已满。
  3. 再看节点和卡资源:哪些节点有空卡,哪些卡被谁占用。
  4. 查卡上的实际进程:确认任务是否真的在计算,还是在空转等待。
  5. 查容器日志和资源监控:有没有 OOM、网络超时、数据读取卡住。
  6. 最后才回头查代码、数据集和训练超参数。

这个顺序能把 80% 的问题挡在代码审查之前。

6.2 高频坑:抢占后没有 checkpoint,越抢越慢

很多团队刚开始做调度时,会直接开抢占策略,高优先级任务一来,低优先级任务立刻被杀。但低优先级任务如果没有定期保存,被杀之后重新排队又要从头算,整体算力消耗是增加的。

正确做法是:给共享集群里的长时间任务开启自动 checkpoint,训练框架每训练一定步数保存一次权重和优化器状态。任务被抢占后,从最近一次 checkpoint 恢复,而不是从零开始。

这里的坑点在于,很多人只在任务正常结束时保存,没有处理“被系统中断”的保存路径。真正要测一次:任务运行到一半强制终止,再重新拉起,看能不能恢复且进度不丢。

6.3 高频坑:数据拷贝时间比训练时间还长

另一个容易被忽略的问题是数据位置。很多团队把训练代码和数据集放在普通文件服务器上,任务在 GPU 节点上跑,每次读取数据都走网络。单个 epoch 的数据量一大,数据传输就成了瓶颈,GPU 只能干等。

判断方法很简单:看任务运行时的 GPU 算力利用率和网络读写速度。如果算力利用率很低,但网络或磁盘的 I/O 很高,多半是数据喂不上。可以先做小规模样本测试,把数据缓存到节点本地,再对比训练耗时;如果差别明显,就要把数据预加载和本地缓存纳入任务规范。

6.4 高频坑:只看单机,忽略多机通信拓扑

多卡训练不是把任务拆到多张卡就行,卡与卡之间的通信速度和拓扑位置直接影响训练效率。同一台机器内部的高带宽互联通常没有问题,但跨机器、跨交换机就可能出现通信瓶颈。

我在实际中见过不少团队,集群里混着不同年代的机器和不同驱动版本,分布式训练任务被调度到两台驱动不一致的机器上,结果直接报错或者训练速度骤降。所以多机训练资源最好固定在一个同构资源池里,并且提前验证通信端口、驱动版本和训练框架版本是否一致。

6.5 有些情况不需要上重平台

写到最后,还是要泼一盆冷水:不是所有团队都需要一套完整的算力调度平台。

如果你的团队只有几台机器、任务量稳定、使用人数不超过一两个,那手动管理或者用一个轻量任务脚本完全够用。此时真正优先做的不是搭平台,而是把环境依赖固定下来、把数据集存放位置定好、把常用训练脚本参数写成模板。资源一旦出现明显的排队和闲置并存现象,再开始引入队列和配额。

我个人的建议是算力组织要按“够用就好”的原则推进:先解决队列问题,再解决优先级问题,然后解决计量和观测问题。平台是工具,不是目的。真正让算力被组织起来的,是一套可执行、可监督、可反馈的规则,以及一批愿意按照规则使用资源的工程师。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询