Slurm 指定 GPU 卡:`File=/dev/nvidiaX` 映射的坑与修复

Slurm 指定 GPU 卡:File=/dev/nvidiaX 映射的坑与修复

这配置不一定是正确的 ,存在一个关键的不确定性:File=/dev/nvidia0 和 /dev/nvidia1 的映射,并不保证 永久对应 nvidia-smi 中显示的 GPU 0(Bus-Id 17:00.0)和 GPU 1(Bus-Id CA:00.0)。

为什么说"不一定对"

Slurm 官方文档明确指出:GPU 设备文件(如 /dev/nvidia0)基于 Linux 次设备号分配,而 NVML(nvidia-smi 背后的库)按 PCI 总线 ID 排序。两者之间的映射关系是不确定的,且依赖于系统,在硬件或操作系统变更后、甚至重启后都可能改变。

你之前遇到的 Reason=gres/gpu count reported lower than configured (1 < 2) 错误,恰恰可能就是这个映射错位导致的:Slurm 通过你写的 File= 去匹配 GPU,但匹配结果与它在 slurm.conf 中期望的数量对不上。

如何验证当前映射是否正确

在你的节点上运行以下命令,检查 slurmd 实际看到的设备文件与 NVML 编号的对应关系:

bash 复制代码
sudo slurmd -G

观察输出中每个 GPU 的 File= 字段是否与你期望的物理卡对应。如果 slurmd -G 显示它把 card0 匹配到了 /dev/nvidia1 而不是 nvidia0,你的配置就会导致调度错位。

更稳妥的做法

既然你的目标是在两块 A100 中指定使用卡零 ,而 File= 映射又不可靠,推荐:

  1. 在 gres.conf 中启用自动探测,并只标记类型:

    复制代码
    AutoDetect=nvml
    Name=gpu Type=card0
    Name=gpu Type=card1

    注意:Type 的值必须是 NVML 返回设备名的子串(A100 通常包含 a100),但 Slurm 允许自定义 Type 作为调度标签,只要与 slurm.conf 中的 Gres= 一致即可。更简单的做法是直接让两块卡用同一个类型名(如 Type=a100),然后在提交作业时通过 --gres=gpu:a100:1 请求,由 Slurm 分配任意一块空闲的。

  2. 如果你确实必须绑定到某一块物理卡 ,则不要依赖自动探测。保持 AutoDetect=off,用 File= 手动指定,但每次驱动重载或重启后 ,都必须用 slurmd -G 或 nvidia-smi 核对 /dev/nvidiaX 与 PCI Bus-Id 的对应关系是否仍然一致。一旦映射漂移,作业就可能被分配到错误的物理 GPU 上。

简单结论:你写的两行配置在语法上没问题,但能否稳定"指定卡零"取决于当前系统里 /dev/nvidia0 是否恰好对应 Bus-Id 17:00.0 的那块 A100。先跑 sudo slurmd -G 确认映射,再决定是否继续用 File= 方式。

根据 slurmd -G 的输出,你的配置在 Slurm 层面被正确解析了,但这并不能保证"卡零"的物理对应关系永久可靠。

输出解读

slurmd -G 显示 Slurm 已经接受了你的两条配置:

  • card0 对应 Index=0、File=/dev/nvidia0
  • card1 对应 Index=1、File=/dev/nvidia1

这说明 Slurm 能够读取并映射这两个设备文件。如果之前导致节点不可用的"数量不匹配"错误(1 < 2)是因为配置语法或文件路径错误引起的,那么现在的输出表明这个问题可能已经解决,节点有希望恢复正常。

关键风险依然存在

你之前担心的"指定卡零"问题,核心不在于 Slurm 是否能解析配置,而在于 /dev/nvidia0 是否永远对应 nvidia-smi 里 Bus-Id 为 17:00.0 的那块 A100。

Slurm 官方文档明确指出,GPU 设备文件(/dev/nvidiaX)基于 Linux 次设备号分配,而 NVML(nvidia-smi)按 PCI 总线 ID 排序,两者之间的映射是不确定的且依赖于系统 ,在硬件变动或系统更新后可能改变。你的 slurmd -G 输出只能证明当前这一刻映射是成立的,但无法提供永久保证。

建议

  1. 先恢复节点 :既然 slurmd -G 显示两块卡都被正确识别,你可以尝试 sudo scontrol update NodeName=yin-PowerEdge-R750 State=RESUME 让节点恢复可用,然后重新提交作业。
  2. 建立验证习惯 :不要假设 /dev/nvidia0 永远是卡零。每次驱动重载、系统重启或硬件变动后,运行一次 sudo slurmd -G,确认 File=/dev/nvidia0 那一行的 Index 和 PCI 顺序是否符合你的预期。
  3. 如果必须绝对锁定 :如果你无法接受映射漂移的风险,最稳妥的方式是放弃在 Slurm 层指定物理卡 。让 Slurm 管理两块卡,在提交作业时用 --gres=gpu:1 请求任意一块空闲卡,然后在训练脚本内部通过 CUDA_VISIBLE_DEVICES 或代码逻辑选择你真正想用的那块。这样 Slurm 的分配和你的物理选择就解耦了。
    你的 gres.conf 配置本身没有问题,slurmd -G 也证明 Slurm 在节点本地 能正确识别两块卡。问题出在 slurmctld(控制节点)与 slurmd(计算节点)之间的信息同步上:控制端仍然拿着旧的"只上报了 1 块卡"的记录,没有更新。

你看到的 Reason=gres/gpu count reported lower than configured (1 < 2),时间戳停留在 04:31:36,说明这个错误状态是之前 留下的,不会因为你执行了 scontrol reconfig 就自动消失。scontrol reconfig 只是让控制端重新读取配置,并不会强制节点重新注册它当前的实际 GPU 数量。

怎么修

直接把这个节点从错误状态里"推"出来,让它重新向控制端注册一次:

bash 复制代码
sudo scontrol update NodeName=yin-PowerEdge-R750 State=DOWN
sudo scontrol update NodeName=yin-PowerEdge-R750 State=RESUME

执行后,用 scontrol show node yin-PowerEdge-R750 | grep -E "State|Reason" 确认。如果 State 变成 IDLE 或 MIXED,并且 Reason 那一行消失或变成 none,就说明节点已恢复,可以重新提交作业。

如果上面两步做完 Reason 仍然不变,可以尝试重启该节点上的 slurmd 服务,强制它重新上报 GPU 信息:

bash 复制代码
sudo systemctl restart slurmd

为什么 reconfig 不够

slurmd -G 只检查本地配置解析,它成功只代表 slurmd 自己知道有两块卡。但节点在 Slurm 里的状态是由 slurmctld 维护的,如果 slurmctld 之前已经因为"只收到 1 块卡"的报告把节点标记为无效,它需要一次新的节点注册事件才会刷新认知。DOWN → RESUME 或重启 slurmd 就是触发这次重新注册的手段。

节点已经恢复正常了。从你最后的输出看:

  • State=MIXED,说明节点已可用,且部分资源被占用(MIXED 表示有作业在跑但还有空闲资源,对你这种单节点场景是正常状态)。
  • Reason 那一行在 grep State|Reason 的输出里已经消失了,说明之前的错误原因被清除了。
  • squeue 显示作业 118 状态为 R(Running),正在节点上运行,已经跑了 24 秒。

也就是说,虽然 grep -i gres 那条命令的输出里还残留着旧的 Reason 行(那是 gres 相关的字段展示,可能带了历史缓存),但节点的实际调度状态已经恢复,作业也成功启动,问题解决了。

关于那两条命令的报错

State=DOWN 被拒绝是因为 Slurm 要求 DOWNING 节点时必须带 --reason,比如:

bash 复制代码
sudo scontrol update NodeName=yin-PowerEdge-R750 State=DOWN Reason="maintenance"

不过你直接执行 State=RESUME 就成功了,说明节点当时已经不在 DOWN/DRAINED 状态,RESUME 起到了刷新作用,这就够了。以后如果确实需要手动 DOWN 节点,记得加上 Reason="..." 即可。

后续建议

  1. 验证作业确实用到了你指定的卡 :作业跑起来后,可以 scontrol show job 118 | grep -i gres 确认它拿到的是 card1(你脚本里写的是 --gres=gpu:card1:1),同时看作业日志里 CUDA_VISIBLE_DEVICES 是否正确映射到了预期的物理 GPU。
  2. 保持对 /dev/nvidiaX 映射的警惕 :slurmd -G 目前显示 card0→/dev/nvidia0、card1→/dev/nvidia1,但如前面所说,这个映射在重启或驱动变动后可能漂移。每次重启后跑一次 sudo slurmd -G 核对一下即可。
  3. 如果再次出现 1 < 2 :同样的套路------先 RESUME 刷新,不行就 sudo systemctl restart slurmd 强制重新上报。

现在作业已经在跑了,可以去看日志确认训练是否正常启动。

相关推荐
叼烟扛炮1 小时前
Linux 学习笔记(三十四):线程同步——条件变量与生产消费者模型
linux·运维·服务器·笔记·学习·1024程序员节
隐擎fox1 小时前
解密 HTTP/2 帧时序与流控指纹:Akamai H2 指纹逆向检测与协议重塑工程实战
网络·网络协议·tcp/ip·http
酣大智1 小时前
hibernate学习笔记
java·hibernate·session
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】Trae生成main方法
网络·人工智能·网络协议·http·架构·1024程序员节
隔窗听雨眠2 小时前
从行为引导到基础设施约束:AGI代理风险缓解的工程化路径
网络·人工智能·agi
国际云,接待2 小时前
云服务器 WebSocket 空闲后频繁断开:查 Nginx 超时、心跳与负载均衡,再评估扩容
服务器·websocket·nginx
pt10432 小时前
Cisco设备网络安全系列-16:微服务、Kubernetes与无服务器架构安全
网络·安全·微服务·架构
Linux界最忧郁之人2 小时前
OpenStack Victoria双节点实战|Packstack一键部署(CentOS‑Stream‑8)+华为云ECS实操
linux·运维·服务器·centos·华为云·openstack
DevNote_2 小时前
1C1G 服务器从零配置实录(附完整命令)
linux·运维·服务器·javascript·adb·ssh·gmssh