从一张GPU到AI集群:节点、任务、并行和调度

一个模型在单张GPU上试跑成功后,训练团队做了个估算:照现在这个速度,完整训练得跑六周。于是公司添置了GPU服务器,指望让更多算力一起把它啃下来。
可硬件一进机房,团队很快就发现,服务器多了只是个开头。八张GPU到底怎么分工,进程之间怎么找到彼此,一个任务该拿走哪几台机器,某个节点跑到一半掉了线又该从哪儿接着来——这些问题,可不会因为网线已经插好就自动消失。
集群在AI里的作用,正是要把这些分散的计算、网络和存储,组织成一个能被任务使用、被团队共享、出了故障还能恢复的系统。这篇导读不教你怎么搭集群,而是想陪着一个训练作业走完它的整个生命周期,好让节点、进程、rank、并行、调度这些概念,都能找到自己的位置。
从一张卡走到多台机器,变的不只是数量
这项训练最开始只用一张GPU。模型、输入和计算全挤在同一块设备上,工程师要操心的,无非是准备好数据和程序。等GPU显存不够用、或者训练慢得受不了,团队先把任务扩到了单机多卡。
一进多卡阶段,设备之间就必须分工了。每张卡可以各存一份模型、各处理一批不同的数据,也可以合起来扛一份单卡装不下的大模型。可无论怎么拆,卡与卡之间都得靠PCIe、NVLink或者NVSwitch来交换梯度和张量。
任务再跨到另一台服务器,消息就还得过网卡、穿交换网络。原先在机箱内部几步搞定的通信,如今一脚跨过了节点的边界。于是"哪张GPU摆在哪台机器上""进程之间要走哪条路径",开始实实在在地影响每一轮计算。
等更多团队也跑来申请GPU,系统还得再处理一层共享的问题。有人要八张卡连用两天,有人只想借一张卡验证半小时,在线服务则希望永远给自己留着一块。所以集群要解决的,就不只是"多张卡怎么一起算",还得是"这么多任务,怎么有秩序地轮着用这些卡"。
一个作业提交上去,几个概念就自然串在了一起
现在团队不再登录某台服务器手工敲命令启动了,而是向平台提交一个作业,也就是Job。这个作业会写清楚:要跑在什么环境里、用什么命令启动、以及需要多少GPU、CPU、内存和存储。平台收到申请,先把它放进队列,等着合适的资源腾出来。
集群里的一台服务器,通常叫做一个节点。一个节点里可以塞着多张GPU、CPU、主机内存、本地存储和高速网卡。调度器要做的,是从这些节点中挑出一组正好满足要求的机器,再把设备分配给作业。
资源就位后,启动工具会在各个节点上把进程拉起来。PyTorch分布式训练常用的做法,是一张GPU对应一个进程,每个进程先算完自己本地那份,再通过通信后端跟同伴对齐。而rank,就是进程在某个通信组里的编号,它让每个参与者都清楚:自己是谁、该跟谁交换数据。
你会发现,节点、作业、进程、rank并不是四条要分开背的定义,而是同一个启动过程里的四个位置:节点提供机器,作业表达要干的活,进程真正把程序跑起来,rank则让这些进程能彼此协作。往后再碰到Task、Pod、Step这些词,结合具体平台去看它们各自怎么表示作业里的执行单元就好。
并行策略,既决定GPU怎么分工,也决定它们怎么通信
调度器把GPU交到作业手上之后,训练框架才开始真正安排计算。如果模型塞得进单卡,可以走数据并行:每张GPU各存一份模型、各处理不同数据,再把梯度同步一下。这招好懂,却治不了"模型本身就超过单卡显存"这个病。
张量并行的办法,是把一次矩阵运算、或者一层的参数拆到好几张GPU上,这样能装下更大的模型,代价是层内部得频繁交换中间结果。流水线并行则把不同的模型层摆到不同阶段,让一个个微批次依次往前推,可它又得对付各阶段忙闲不均、互相等待的问题。碰上混合专家模型,还可能靠专家并行拉出一片All-to-All通信。
入门阶段,你不必把每种并行的完整算法都吃透,但一定要看出它们共同的那层关系:计算拆得越散,通信和协调通常就越吃重。 加GPU到底划不划算,从来不只看卡数,还得看省下来的那点计算时间,够不够抵掉新添出来的同步和等待。这也正是集群学习会跟网络学习交叉的地方——并行策略决定了要交换什么,NCCL这类通信库帮进程把集合通信做完,而网络和拓扑,则决定了这些数据到底得跑多远。
调度器只负责"找座位",不负责"决定模型怎么切"
这项作业申请的是单节点八张GPU,却在队列里等了好久。管理员一查集群,发现四台服务器每台都空着两张卡,加起来正好八张——数是够了,可偏偏没有哪一台机器,能独自凑出完整的一组八卡。
这就是资源碎片。它特别像剧院里还剩八个空座,却怎么也找不出八个连在一起的位置。而一旦把GPU型号、显存容量、MIG规格、网卡拓扑、本地数据的位置这些因素都算进来,"到底有没有可用资源"这件事,就远比数一数空闲总数要复杂得多。
调度器要做的,是维护好节点状态、处理队列和配额、挑出资源再把作业启动起来。它可以尽量把通信密集的进程摆到合适的位置,但它绝不会替训练程序去决定"模型的某一层该切到哪张GPU"。并行是框架和应用的事,分配是调度的事,两边必须配合着来。所以学集群调度,也别只盯着GPU平均利用率——作业排了多久的队、关键任务什么时候能完成、能凑出多少组适配的资源、不同团队用得公不公平,这些才是平台真正要去经营的结果。
从启动一路到故障恢复,才算一条完整的生命周期

现在可以把这项作业从头串一遍了。用户提交配置,作业进入队列;调度器找到符合要求的节点和GPU,完成资源绑定;各节点把进程拉起,进程再根据地址和rank建立起通信,加载好模型与数据,随后进入持续的计算。
监控系统则在一旁默默记录着训练进度,以及GPU、显存、网络、数据读取和各种错误。别忘了,同步训练里只要一个进程掉了队,就可能拖着整组GPU陪它一起等——所以平台不能只看平均状态,还得能揪出那个总是最慢的设备和那条总是最堵的路径。
到了预定时刻,进程们会一起保存检查点。万一之后某个节点离线了,调度平台固然可以重新找资源、把程序再拉起来,可作业能不能真的接着跑,还得看有没有一份完整、读得出来的检查点。要是只会重启容器、却恢复不了模型状态,那训练还是得从头再来一遍。
正因如此,AI集群管理的,远不止"把设备分出去"这一件事。提交、排队、启动、通信、监控、保存、失败、重试、恢复,这一整串合起来,才构成一个作业的生命周期。往后你学任何一样平台工具,都可以把它放回这条流程里,看看它到底负责的是哪一段。
Kubernetes和Slurm,是管理这条流程的两个不同入口
Slurm长期扎根在高性能计算和批作业调度领域,它擅长队列、资源申请、整组分配、作业步骤和用量核算,也能通过GRES来管GPU这类资源。训练作业提交上去先排队,拿到一组节点,一口气跑到结束——这种工作方式,跟它特别合拍。
Kubernetes则以容器编排为核心,长处在声明式部署、长期服务管理和故障重建。装上设备插件之后,GPU就能作为一种资源交给Pod;团队还能在这个底座上,再叠加批调度、队列和各种AI平台能力。
入门文章没必要非把这两者分个胜负。以离线训练和传统HPC为主的环境,也许会从Slurm起步;在线推理和云原生服务偏多的团队,可能对Kubernetes更顺手;而大型组织,完全可能让不同的资源池各用各的平台。至于具体怎么选,还得结合工作负载、团队经验、配额、网络、存储、监控和故障恢复,留到后面单独去掰扯。
训练和推理,会让集群跑出不一样的节奏
训练作业往往需要成组的GPU,一跑就是几小时到几周,它可以排队等,却格外在意整体要跑多久、并行效率高不高、检查点能不能顺利恢复。在线推理则要一刻不停地接请求,更操心的是延迟、吞吐、扩缩容和版本发布。
当多个推理副本各自独立时,平台大可把请求分散到不同的GPU上;可一旦模型必须跨卡拆分、KV Cache需要远端传输,推理同样会结出紧密的通信和状态依赖。把训练和推理塞进同一个资源池,并非不行,但网络、存储和资源预留,都可能在里头互相干扰。所以学集群,得始终分清工作负载——调度器管的从来不是抽象的"一堆GPU",而是一个个有持续时间、有并行方式、有优先级、有服务目标的具体任务。
这条AI集群学习路线,可以怎么走
后续学习,不妨就跟着一个作业的生命周期,一步步往深里走:
先认清运行对象:把节点、作业、任务、进程、rank和通信组之间的关系理顺。
再学并行与集合通信:认识数据并行、张量并行、流水线并行、专家并行,以及NCCL这类通信工具。
接着学资源调度:继续弄懂队列、配额、优先级、整组调度、资源碎片和拓扑感知。
然后学运行观测:把GPU利用率、显存、网络、存储等待、训练进度和日志放在一起分析。
再学可靠性:进入健康检查、检查点、重试、故障隔离和恢复流程。
最后比较平台:深入Kubernetes设备调度、批调度体系、Slurm GRES,以及不同资源池的管理方式。
从一张GPU走到AI集群,表面看只是设备越来越多,可真正要学的,是怎样让许许多多进程,在一组被统一调度的资源上协作,并在故障之后,继续把同一项任务干完。
接下来可以读什么
刚开始学,可以先读算力资源总览;准备理解多机训练,就接着看高速网络和高速存储的导读;如果你负责的是平台建设,那就沿着作业的生命周期,一路深入并行框架、NCCL、资源调度、Kubernetes、Slurm和分布式检查点这些专题。
站内关联阅读
参考资料
PyTorch Distributed:https://docs.pytorch.org/docs/stable/distributed
PyTorch DistributedDataParallel:https://docs.pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html
NVIDIA NCCL User Guide:https://docs.nvidia.com/deeplearning/nccl/user-guide/docs/overview.html
Kubernetes, Schedule GPUs:https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/
Kubernetes, Dynamic Resource Allocation:https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/
Slurm GRES Scheduling:https://slurm.schedmd.com/gres.html
PyTorch Distributed Checkpoint:https://docs.pytorch.org/docs/main/distributed.checkpoint.html