用 GRES 定义 GPU
一句话总结
在 Slurm 中,GPU 被视为一种名为 GRES(Generic RESource) 的通用设备资源。两个文件必须相互匹配——slurm.conf 与 gres.conf。
为什么需要 GRES
Slurm 可以自行统计 CPU 和内存,但 GPU 呢?FPGA 呢?NVMe 呢?Slurm 无法直接识别这些设备,因此建立了一套由管理员声明资源的机制,这就是 GRES。
它是如何工作的
两个文件各自的职责
| 文件 | 填写什么 | 部署范围 |
|---|---|---|
slurm.conf |
存在哪些 GRES 类型,以及每个节点各有多少资源 | 所有节点保持一致 |
gres.conf |
这些 GRES 实际对应哪些设备文件 | 每个节点可以不同 |
slurm.conf 这一侧:
GresTypes=gpu
NodeName=gpu-node01 ... Gres=gpu:a100:4 State=UNKNOWN
gres.conf 这一侧:
NodeName=gpu-node01 Name=gpu Type=a100 File=/dev/nvidia[0-3] Cores=0-15
两边的数量必须完全一致。 如果 slurm.conf 中写的是 gpu:a100:8,而 gres.conf 中的 File=/dev/nvidia[0-3] 只代表 4 块设备,slurmd 就会在日志中留下 gres/gpu count reported lower than configured,并将节点置于 DRAIN 状态。这是最常见的 GRES 配置错误。
Cores 与 NUMA 亲和性
NodeName=gpu-node01 Name=gpu Type=a100 File=/dev/nvidia0 Cores=0-15
NodeName=gpu-node01 Name=gpu Type=a100 File=/dev/nvidia1 Cores=0-15
NodeName=gpu-node01 Name=gpu Type=a100 File=/dev/nvidia2 Cores=16-31
NodeName=gpu-node01 Name=gpu Type=a100 File=/dev/nvidia3 Cores=16-31
Cores= 用于指出与该 GPU 在物理上相邻、也就是连接到同一 NUMA 节点的 CPU 核心。Slurm 会利用这些信息把 GPU 与 CPU 安排在同一个插槽,从而减少 PCIe 往返传输。大规模训练中,这会带来几个百分点的性能差异。
可以使用 nvidia-smi topo -m 查看实际拓扑。
AutoDetect
AutoDetect=nvml
它通过 NVML 库自动探测 GPU,并自动填入设备文件与 NUMA 亲和性,使用起来很方便;但前提是系统已经安装 NVML,而且 Slurm 构建时启用了它。 此外,如果自动探测结果与 slurm.conf 中的声明不同,节点仍然会退出——自动探测并不能代替验证。
手工定义比较麻烦,但它明确且可复现。在隔离网络或异构集群中,手工配置往往更加安全。
MIG
在 A100/H100 上使用 MIG 时,一块物理 GPU 会被切分为多个实例。此时,每个 MIG 实例都会成为独立的 GRES 项,Type= 中填写配置文件名称。
NodeName=gpu-node01 Name=gpu Type=1g.10gb File=/dev/nvidia-caps/...
MIG 配置改变时,gres.conf 也必须同步改变。 如果不自动化这个过程,每次重新配置 MIG 都会使节点退出。
申请 GPU
sbatch --gres=gpu:2 train.sh # 타입 무관 2장
sbatch --gres=gpu:a100:2 train.sh # a100 2장
sbatch --gpus=2 train.sh # 최신 문법
sbatch --gpus-per-node=2 --nodes=2 train.sh # 노드당 2장씩 총 4장
作业内会自动设置 CUDA_VISIBLE_DEVICES。其中的值不是物理设备编号,而是从 0 开始的逻辑编号。因此,不能在代码中硬编码物理编号。
实际工作中会遇到的情况
GPU 数量不一致。 节点上的一块 GPU 因硬件故障消失,配置却保持不变。slurmd 会报告数量不一致,并将节点置于 DRAIN 状态。这个告警反而是一件好事——它总比让作业继续使用故障 GPU 并产生异常结果要好。
没有填写 Cores=,导致性能不佳。 如果 GPU 和 CPU 被安排到不同插槽,数据就必须跨 PCIe 传输。这种影响在多 GPU 训练中尤为明显。
下一个实验要做什么
在 slurm.conf 中声明 GRES 类型和每个节点的 GPU,编写 gres.conf,并进一步验证两个文件中的数量是否一致。