GPU集群架构:典型硬件拓扑与调度系统简介
分布式训练任务的中断,往往并非源于代码逻辑本身,而是源于底层硬件拓扑与调度系统之间的“错配”。理解集群的物理连接方式与资源管理策略,是分析任务中断根因的第一道门槛。本节聚焦两类核心硬件互联(NVLink与InfiniBand)和两类主流调度系统(Slurm与K8s),帮助您建立从“一张显卡”到“整柜集群”的完整视图。
3.1 典型硬件拓扑:从单机到跨节点
GPU服务器内部与服务器之间,存在两种截然不同的通信路径。混淆这两条路径,是许多网络超时中断的根源。
3.1.1 节点内互联:NVLink与NVSwitch
NVLink是NVIDIA推出的高带宽、低延迟点对点互联总线,用于GPU与GPU、GPU与CPU之间的直连。在8卡DGX或HGX服务器中,通常采用全连接(All-to-All)或NVSwitch两种拓扑:
- 全连接拓扑:每块GPU通过NVLink直接与其他GPU相连(如A100 4卡全连接),适合小规模张量并行。
- NVSwitch拓扑:引入独立交换芯片,实现8卡或更多GPU之间的无阻塞全互联。任何两块GPU之间的通信带宽一致,无需经过PCIe交换机。
NVLink的典型带宽为:A100单链路50GB/s(双向),H100单链路90GB/s(双向)。在8卡H800服务器中,每块GPU通常拥有8条NVLink链路,总双向带宽可达900GB/s。若训练任务中使用了张量并行(如Megatron-LM的TP=8),则节点内通信必须走NVLink,否则性能会断崖式下降。
nvidia-smi nvlink -s命令输出的链路状态,确认所有链路处于Active状态。
3.1.2 跨节点互联:InfiniBand与RoCE
当模型规模超出单机显存,需要多机并行时,节点间通信依赖高速网络。目前主流方案是InfiniBand(IB)和RoCE(RDMA over Converged Ethernet)。
InfiniBand采用专用交换机和网卡(HCA),提供RDMA(远程直接内存访问)能力,延迟低至微秒级。常见速率为HDR(200Gb/s)、NDR(400Gb/s)。在训练集群中,IB网络通常采用胖树(Fat-Tree)或Torus拓扑,保证任意两个节点间的带宽接近线速。
RoCE则运行在以太网上,分为RoCEv1(L2)和RoCEv2(L3)。RoCEv2需要配置流控(PFC)和ECMP,对交换机缓冲要求较高,否则容易出现丢包导致训练中断。
| 特性 | NVLink | InfiniBand | RoCEv2 |
|---|---|---|---|
| 通信范围 | 节点内(GPU-GPU) | 跨节点(服务器间) | 跨节点(服务器间) |
| 典型带宽 | 50-100GB/s/链路 | 200-400Gb/s/端口 | 100-400Gb/s/端口 |
| 延迟 | 亚微秒级 | 1-3微秒 | 2-5微秒(依赖交换机) |
| 协议 | 专有协议 | RDMA | RDMA over Ethernet |
| 主要用途 | 张量并行、数据并行梯度同步 | 数据并行、流水线并行跨节点通信 | 低成本跨节点通信 |
| 故障表现 | Xid错误、链路降速 | IB丢包、端口Down | PFC死锁、ECMP哈希不均 |
3.2 调度系统:谁来决定任务跑在哪
调度系统负责分配GPU资源、排队任务、监控作业状态。不同调度系统对任务中断的处理方式截然不同,理解其差异有助于快速定位“任务为何被杀”或“为何卡在排队中”。
3.2.1 Slurm:传统HPC作业调度
Slurm(Simple Linux Utility for Resource Management)是学术与超算中心最常用的调度器。它采用分区(Partition)+ 作业(Job)模型,用户通过sbatch或srun提交作业,由slurmctld统一调度。
关键概念:
- Partition:节点分组,如
gpu-a100、gpu-h800,不同分区可设置不同QoS与优先级。 - Job Step:一个作业内可包含多个步骤(如数据加载、训练、评估)。
- 资源限制:通过
--gres=gpu:8申请GPU数量,--nodes=2申请节点数。
# 提交一个使用2节点、每节点8卡的任务
srun -p gpu-h800 --nodes=2 --gres=gpu:8 --ntasks-per-node=8 \
--cpus-per-task=16 --time=48:00:00 \
python train.py --config configs/llama2_70b.yaml
Slurm中任务中断的常见原因包括:
- 超时被杀:
--time设置过短,作业到达时间上限后Slurm发送SIGTERM,若未优雅退出则SIGKILL。 - 节点故障:节点宕机或GPU异常,Slurm会将作业置为
FAILED或NODE_FAIL。 - 抢占:高优先级作业到来时,低优先级作业可能被抢占(Preempt)。
--requeue标志或自研看门狗脚本)实现自动恢复。务必在提交脚本中设置--requeue,并让训练代码支持断点续训。
3.2.2 Kubernetes:云原生容器调度
K8s将GPU作为可调度的扩展资源(nvidia.com/gpu),通过Device Plugin插件上报GPU数量。与Slurm不同,K8s以Pod为最小调度单位,支持容器化训练任务。
在K8s中运行分布式训练,通常使用以下方式:
- Job / CronJob:适用于单任务或定时任务。
- MPI Operator:为MPI风格分布式训练提供CRD(自定义资源),自动创建Worker与Launcher。
- PyTorchJob / TFJob:来自Kubeflow,专门管理PyTorch或TensorFlow的PS/Worker架构。
# PyTorchJob 示例(Kubeflow)
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
name: pytorch-simple
spec:
pytorchReplicaSpecs:
Master:
replicas: 1
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.1.0-cuda12.1
command: ["python", "-m", "torch.distributed.run", "--nproc_per_node=8", "train.py"]
resources:
limits:
nvidia.com/gpu: "8"
Worker:
replicas: 2
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.1.0-cuda12.1
command: ["python", "-m", "torch.distributed.run", "--nproc_per_node=8", "train.py"]
resources:
limits:
nvidia.com/gpu: "8"
K8s任务中断的典型场景:
- OOMKilled:容器内存超限被cgroup杀掉。
- 节点压力驱逐:节点磁盘或内存不足,kubelet触发Eviction。
- GPU异常:Device Plugin上报的GPU不健康,调度器不会将Pod调度到该节点。
- 抢占与优先级:PriorityClass低的Pod可能被高优先级Pod抢占。
3.3 调度系统与硬件拓扑的交互:NCCL的视角
NCCL(NVIDIA Collective Communications Library)是分布式训练中负责GPU间通信的核心库。它需要感知底层拓扑才能选择最优通信路径。当调度系统分配的节点或GPU位置与NCCL的预期不符时,就会出现性能骤降甚至通信超时。
NCCL通过拓扑探测构建通信树:
- 启动时调用
ncclTopoDetect,读取PCIe、NVLink、IB链路信息。 - 根据GPU所在NUMA节点、NVLink连接关系,构建intra-node与inter-node通信图。
- 选择Ring或Tree算法进行AllReduce。
若调度系统将任务分散到不同机柜的节点,而节点间IB带宽不足,NCCL可能回退到TCP/IP通信,导致训练速度骤降。此时可通过设置环境变量强制指定网卡:
export NCCL_IB_DISABLE=0
export NCCL_IB_HCA=mlx5_0,mlx5_1
export NCCL_SOCKET_IFNAME=ib0
export NCCL_DEBUG=INFO # 打印实际使用的通信路径
NCCL_DEBUG=INFO日志发现,NCCL将通信路径识别为“TCP/IP”,而非“IB”。原因是Pod未设置hostNetwork: true,导致容器内无法访问IB网卡设备。修复方法:在Pod spec中增加hostNetwork: true并挂载/dev/infiniband设备。
3.4 常见误区与避坑清单
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 认为NVLink与IB可以混用 | 跨节点通信误走NVLink(实际不可达),导致初始化失败 | 明确区分节点内/跨节点通信,NCCL会自动选择,但需确保IB网卡驱动正常 |
Slurm作业不设置--requeue | 节点故障后作业直接失败,无自动恢复 | 添加--requeue,并实现checkpoint保存 |
| K8s Pod未暴露IB设备 | NCCL回退到TCP,性能暴跌 | 使用hostNetwork或SRIOV设备插件 |
| 忽略NUMA亲和性 | GPU跨NUMA访问内存,延迟增加30%以上 | 使用nvidia-smi topo -m检查,设置CPU绑核 |
| 所有节点使用同一IB子网但未配置路由 | 跨子网通信失败,任务挂起 | 检查ibstatus,确保子网管理器(SM)运行正常 |