GPU 集群调度:高效分配多用户训练任务

FreeGuideOnline 最新 2026-06-28

GPU 集群调度:高效分配多用户训练任务

在多用户共享的深度学习环境中,GPU 资源既是昂贵的算力资产,也是耗时任务争夺的焦点。一套优秀的调度系统能够将等待时间从数天压缩至分钟级别,同时将整体集群利用率从 30% 提升到 80% 以上。本教程从零讲解 GPU 集群调度的核心原理、主流策略和实战技巧,助你构建高效的多人训练平台。


1. 为什么需要 GPU 集群调度

1.1 单机训练 vs 集群训练

  • 单机瓶颈:个人独占一台 4-GPU 或 8-GPU 机器时,资源不可分片,多任务只能串行执行,大量时间浪费在排队和手动切换上。
  • 集群诉求:当 10 个研究员提交混合了 1 卡、4 卡、8 卡需求的训练任务,若没有调度器,只能靠白板或 Excel 协调,必然导致资源碎片化、饥饿和冲突。

1.2 调度系统的核心目标

  • 公平性:按权重、配额或优先级分配 GPU 时间,防止某些用户长期霸占资源。
  • 效率:尽可能减少 GPU 空闲时间,提升集群整体吞吐量。
  • 弹性与灵活性:支持动态加入/退出节点、不同规格 GPU(A100 / V100 / RTX)混部、可抢占式任务等。
  • 隔离性:任务之间互不干扰,避免 GPU 显存溢出、网络拥塞等连锁效应。

2. GPU 集群调度的核心概念

2.1 作业与任务

  • 作业(Job):用户提交的一次完整训练行程,例如“训练 ResNet-50 到收敛”。
  • 任务(Task):作业在每块 GPU 或每个计算节点上运行的实例。一个 4 卡分布式作业通常包含 4 个任务。
  • Pod(Kubernetes 语境):Kubernetes 中调度的最小单元,一个 Pod 可请求 1 块或多块 GPU。

2.2 资源需求与拓扑

调度器需要理解任务对资源的细粒度请求:

  • GPU 数量resources.requests.nvidia.com/gpu: 4
  • GPU 类型:需要 A100-80GB 还是 V100-32GB?
  • 隐式资源:CPU 内存(通常多卡训练需要与 GPU 数成比例的 CPU 内存)、IB 网络带宽、NVLink 拓扑亲和性。
  • 放置约束:分布式训练要求所有 GPU 分布在同一台机器或跨机器但需高带宽连接,调度器必须感知 NUMA 和 NVSwitch 拓扑。

2.3 队列与优先级

  • 多级队列:按部门、项目或紧急程度划分为不同队列,每个队列分配资源上限和权重。
  • 优先级:数值越大越优先调度;非抢占式优先级简单但可能饿死低优任务;抢占式优先级会驱逐已有任务,适合高优紧急训练。

2.4 抢占与驱逐

  • 抢占(Preemption):高优先级任务找不到资源时,可强制终止低优先级任务,释放资源后重新调度。
  • 优雅终止:对支持 checkpoint 的作业先发 SIGTERM 保存模型状态,再重新排队恢复,称为“可恢复抢占”。
  • 饥饿预防:设置最小保障资源等机制,防止低优先队列永远得不到 GPU。

3. 主流的调度策略与算法

3.1 基础策略

  • 先进先出(FIFO):最简单的策略,按提交顺序执行,资源利用率低,不适合多用户环境。
  • 公平分享(Dominant Resource Fairness, DRF):不仅考虑 GPU 数,还考虑 CPU、内存等多维资源的主资源权重,避免单维度资源饥饿。
  • 容量调度(Capacity Scheduling):为每个组织固定预留一定资源,剩余资源可弹性共享。

3.2 面向深度学习的拓扑感知调度

  • 节点亲和与反亲和:要求同作业的所有 Pod 尽量调度到同一台物理机或同一个交换机组(podAffinity)以减少跨节点通信。
  • GPU 拓扑感知:通过 NVIDIA Topology 文件理解 GPU 之间的 NVLink、PCIe 关系,优先捆绑调度有高带宽连接的 GPU(例如同一 NVSwitch 下的 8 卡)。
  • Gang Scheduling(成组调度):分布式作业需要的所有 GPU 必须同时分配,否则全体等待,避免部分分配导致的死锁和资源占用。常用协议包括“All-or-Nothing”。

3.3 回填与资源碎片整理

  • 回填(Backfilling):在保证队首大作业不延迟的前提下,将后面可立即执行的小作业前移,填补因大作业等待造成的空闲窗口。
  • 碎片整理(Defragmentation):通过离线驱逐、在线迁移等手段重新打包零散 GPU,腾出完整的 8 卡节点。

3.4 弹性调度与超卖

  • 弹性作业:允许作业在运行过程中动态增减 GPU 数量,例如 TorchElastic。
  • GPU 超卖(Overcommit):允许同一块 GPU 上同时运行多个推理任务或显存需求小的任务,常配合 MPS(Multi-Process Service)或 MIG(Multi-Instance GPU)使用。

4. 常用 GPU 调度平台一览

4.1 Slurm + Pyxis/Enroot(HPC 风格)

  • Slurm:传统 HPC 调度器,通过 gres.conf 配置 GPU 为通用资源。
  • 容器支持:借助 Pyxis 插件可在 Slurm 作业中透明使用 Docker/NGC 容器。
  • 优点:成熟稳定、功能丰富,支持 GANG、回填、抢占等。
  • 缺点:原生 Kubernetes 集成较弱,操作界面对云原生用户不够友好。

4.2 Kubernetes 原生方案(K8s + 设备插件)

  • 设备插件框架:NVIDIA device plugin 将 GPU 注册为可调度资源。
  • 调度器插件:默认 kube-scheduler 支持简单 GPU 数量匹配,但不支持拓扑、Gang 调度。
  • Volcano(云原生批量调度):由华为开源,专为高性能工作负载设计,提供 Gang Scheduling、队列管理、公平性、优先级抢占等,是当前 K8s 上最成熟的 GPU 批量调度引擎。
  • Yunikorn:Apache 项目,提供层次化队列和公平调度,支持跨集群资源管理。
  • Kueue:Kubernetes SIG 项目,定位资源配额与队列管理,与通用调度器解耦,适合“提交即排队”的场景。

4.3 专用 ML 平台

  • Run:ai:将整个 GPU 集群抽象为弹性资源池,提供细粒度的动态分配(Fractional GPU)、优先级、配额和作业排队。
  • Determined AI / HPE Machine Learning Development Environment:内置调度器,支持多用户实验排队、抢占和分布式训练。
  • Microsoft Singularity:面向内部大模型训练的全局调度器,强调透明且可抢占的弹性资源。

5. 从零搭建一个可用的 GPU 调度集群(K8s + Volcano 示例)

以下步骤带你快速建立一个支持 Gang 调度、队列、优先级的 GPU 集群环境。

5.1 环境准备

  • 安装 Kubernetes(版本 >=1.21),配置 GPU 工作节点并安装 NVIDIA 驱动和容器运行时 (nvidia-docker2)。
  • 部署nvidia-device-plugin 以暴露 GPU 资源。

5.2 安装 Volcano

kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml

确认组件运行:

kubectl get all -n volcano-system

5.3 创建队列与优先级类别

定义两个队列:urgent(权重 2)和 normal(权重 1),并设置资源上限。

apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: urgent
spec:
  reclaimable: true
  weight: 2
  capability:
    cpu: "20"
    memory: "40Gi"
    nvidia.com/gpu: "8"
---
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: normal
spec:
  reclaimable: true
  weight: 1
  capability:
    cpu: "40"
    memory: "100Gi"
    nvidia.com/gpu: "16"

创建 PriorityClass:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000
globalDefault: false

5.4 提交一个 Gang 调度作业

使用 Volcano 的 Job 资源,指定 minAvailable 确保所有 Pod 一起启动。

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: tf-dist-train
spec:
  minAvailable: 2   # 等待 2 个 Pod 都具备资源后同时启动
  schedulerName: volcano
  queue: normal
  priorityClassName: high-priority
  tasks:
    - replicas: 1
      name: ps
      template:
        spec:
          containers:
            - name: ps
              image: tensorflow/tensorflow:latest-gpu
              resources:
                limits:
                  nvidia.com/gpu: 1
    - replicas: 1
      name: worker
      template:
        spec:
          containers:
            - name: worker
              image: tensorflow/tensorflow:latest-gpu
              resources:
                limits:
                  nvidia.com/gpu: 2

提交后,只有当集群中同时存在 2 块 GPU 给 worker 和 1 块给 ps 时,作业才会启动,避免资源浪费。

5.5 验证调度行为

  • 查看队列状态:kubectl get queue -o yaml
  • 查看作业等待原因:kubectl describe job.batch.volcano.sh <job-name>
  • 资源不足时会看到事件 Pending: insufficient resources

6. 多用户环境下的运维最佳实践

6.1 设置合理配额与限额

  • 使用 ResourceQuota 限制每命名空间(团队)的 GPU 总量。
  • 为个人用户设置 LimitRange 防止单作业申请过多 GPU 导致其他任务饥饿。
  • 对存储和网络也设置限额,防止 IO 风暴影响所有用户。

6.2 监控与告警

  • 集成 Prometheus + Grafana,监控 GPU 利用率、显存使用、温度、功耗(通过 DCGM Exporter)。
  • 监控队列排队深度、平均等待时间、作业完成率。
  • 设置告警:当某个队列等待时间超过 2 小时,或 GPU 空闲超过 30 分钟,通知管理员。

6.3 检查点与弹性恢复

  • 训练代码必须支持自动保存检查点并对 SIGTERM 信号做出响应。
  • 调度器配合 Job Operator 实现失败自动重新排队。
  • 推荐使用 TorchElastic (PyTorch)或 tf.train.Server (TensorFlow) 的容错机制。

6.4 混合工作负载管理

  • 白天优先交互式 Notebook 和短时训练,夜间运行长时间大批量作业。
  • 利用 MIG(A100)或 MPS(Volta/Turing)切分 GPU,将碎片资源分配给推理或开发任务。
  • 通过自定义资源定义(CRD)区分训练作业和推理作业,设定不同生命周期策略。

6.5 拓扑与网络微调

  • 为分布式训练作业添加 topologyKey: kubernetes.io/hostname 的反亲和,强制同一作业的 Pod 跨节点分布(用于 NCCL 多机通信测试)。
  • 若集群使用 InfiniBand,需将 IB 设备也作为调度资源,并通过 Volcano 的 nodeSelectoraffinity 匹配。

7. 常见问题与排错指南

问题现象 可能原因 解决方案
作业一直 Pending,无任何 Pod 创建 Gang 调度条件不满足 检查集群空闲 GPU 是否满足 minAvailable;调整队列回收阈值
部分 Pod 启动后立即被杀死 启动顺序依赖不满足或 CrashLoop 配置 InitContainer 等待主节点就绪,检查日志
低优先级作业永远无法执行 缺乏抢占策略或资源被高优队列吸干 为每个队列设置“保底资源(guaranteed)”,启用公平分享
GPU 显存不足错误 其他进程占用或任务内存泄漏 启用 GPU 显存隔离(NVIDIA device plugin Mixed mode),监控显存并限制
跨节点训练速度明显低于预期 网络拓扑或亲和性未配置 使用 ib_write_bw 测试带宽,通过拓扑感知调度将 Pod 绑定到同一交换机节点

8. 进阶方向与未来趋势

  • 基于预测的弹性调度:通过历史负载预测未来资源需求,提前扩缩容,减少作业等待时间。
  • 成本驱动调度:在多集群或多云环境中,结合算力价格、电费碳排放等因素,调度到成本更低的区域。
  • 大模型时代的特殊需求:千卡以上规模训练要求调度器能感知光交换机拓扑、支持多 Job 协同(Pytorch Fully Sharded Data Parallel)、与存储 I/O 协同调度。
  • 与 CI/CD 流水线集成:将模型训练批处理作业与 ML 流水线(Kubeflow、Airflow)自动触发,形成端到端调度闭环。

9. 总结

GPU 集群调度的本质是在公平性、利用率和执行速度之间达成平衡。对于起步团队,Kubernetes + Volcano 是最快获得企业级调度能力的组合;传统 HPC 用户则可在 Slurm 生态内实现高级策略。无论选择哪条技术栈,务必遵循配额划界、优先级驱动、拓扑感知、弹性恢复这四个设计原则,并持续通过监控数据优化配置。当你的调度器能透明、高效地支撑数十人的日常训练,你便拥有了一座可扩展的 AI 算力工厂。