关于 tao-run-on-slurm
tao-run-on-slurm 是面向 TAO 工作流的 SLURM 集群运行技能,供需要使用远程 GPU 集群的用户运行任务。它通过 SSH 提交和管理作业,并要求数据及镜像在 GPU 分配前准备到共享存储。
主要功能
- 01通过 SSH 提交 SLURM 作业
- 02查询状态、查看日志和取消作业
- 03支持单节点与多节点任务
- 04GPU 作业前准备容器镜像和数据
- 05检查集群及 SSH 前置条件
适用场景
- 01在共享 Lustre 上运行 TAO 训练任务
- 02查看远程作业状态及输出日志
- 03取消已提交或运行中的作业
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nvidia/ skills --skill tao-run-on-slurm安装后在 Claude Code 中输入/tao-run-on-slurm确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BENCHMARK.mdskill-card.mdskill.oms.sigconfig/skillspector-baseline.yamlevals/evals.jsonreferences/cosmos-slurm-guardrails.mddetailed-guide.mdskill_info.yamlslurm-container-execution.mdslurm-preflight-storage.mdslurm-ssh-credentials.md详细介绍
SLURM
单独安装? 如果此会话并非由 TAO 技能库插件初始化,请先运行
tao-setup技能(主机预检、凭据、跨技能发现)。
面向由 SLURM 管理的集群的远程 GPU 计算平台。作业通过 SSH 从启动主机提交到登录节点,暂存到共享文件系统,再使用 sbatch 提交,并通过 srun 容器支持执行。
适用场景
当用户可以使用受管理的 GPU 集群、共享 Lustre 存储以及由调度器分配的 GPU 时,使用 SLURM。如果文件仅存在于 Agent 机器上,请勿使用 SLURM;数据和输出必须能从集群访问。
预检 + SSH
确认已导出 SLURM_USER 和 SLURM_HOSTNAME,并且可以通过无密码 SSH 连接到登录主机(ssh -o BatchMode=yes)。
启动主机需要 ssh,不需要本地 sbatch、srun、Enroot 或 Lustre 挂载。请在选定的远程登录节点/计算节点环境中预检调度器、Pyxis、Enroot 和共享存储依赖项。可通过 SSH 标准输入传送已安装技能中的特定模型检查器;不要暂存临时源代码补丁,也不要将启动主机当作 SLURM 环境。
对于私有 nvcr.io 镜像,请在集群上为每个(集群、用户)组合安装一次 ~/.config/enroot/.credentials:Pyxis/Enroot 不会从作业环境读取 NGC_KEY,如果没有持久凭据,受身份验证保护的拉取会在作业启动时因 "Could not process JSON input" 失败。请通过 printf | ssh heredoc 安装,以确保 NGC_KEY 的值不会写入 shell 历史记录、中间文件或聊天输出;切勿对该值使用 cat/echo。
如果预检失败,Agent 会提示用户通过 Bash 授权安装/修复。可通过 pip 安装的 Python 依赖项除外:自动安装,然后重新运行预检。
完整预检脚本、enroot 凭据 heredoc、前置密钥设置(密钥对、ssh-copy-id、known_hosts、容器密钥挂载、2FA 处理)以及 SSH 故障修复提示,请参阅 references/slurm-ssh-credentials.md。
执行 — 四个动词
tao-run-on-slurm 是平台使用方:通过 ssh + sbatch/squeue/sacct/scancel 运行 spec-bundle,仅修改 job-record。存储属于A 层(Lustre)——提交前将数据集暂存到共享路径,并通过 Pyxis 读取;切勿在分配的计算资源内获取 S3 数据(调度器会因 GPU 空闲超时终止作业,浪费的时间仍会计费)。$BANK = ${TAO_SKILL_BANK_PATH};$LOGIN = 已解析的 SLURM_HOSTNAME。
提交
- 复用已暂存的内容 — 绝不重复操作(A 级):
- 镜像:
@@IMAGE@@是 Lustre 上的.sqsh— 如果已有镜像,请复用 (ssh $LOGIN ls <sqsh>);只有在镜像不存在时,才用enroot import转换一次(按名称缓存 — 参见references/slurm-container-execution.md)。 - 数据集: 确认数据集已在 Lustre 上(
ssh $LOGIN test -e …),并 引用这些路径;tao-data-io只暂存尚不存在的小型辅助输入 — 绝不重新暂存已有数据,也绝不在分配到的计算资源内暂存训练 集。 然后在 Lustre 上使用这些路径编写规格文件:<job_dir>/specs/spec.yaml。
- 镜像:
- 凭据 → sidecar(绝不内联): 如果运行需要会话凭据
(例如
HF_TOKEN),请将其写入 Lustre 上权限为 600 的 sidecar,并让模板在退出时将其彻底删除;NGC 镜像拉取使用一次性的~/.config/enroot/.credentials(参见references/slurm-ssh-credentials.md), 而不是作业环境:set -a; source /path/to/.env; set +a # omit if already exported printf 'export HF_TOKEN=%s\n' "$HF_TOKEN" | ssh $LOGIN "umask 077; cat > <job_dir>/job_$JOB_ID.env" - 打开记录 — 在启动前生成 ID,并绑定 Lustre 上的
results_dir:JOB_ID=$("$BANK/scripts/tao_job_record.py" open --platform slurm --image "$IMAGE" \ --network-arch "$ARCH" --action "$ACTION" --storage-tier A --results-root "$SLURM_BASE_RESULTS_DIR") - 使用可选的模型生命周期。 如果已验证的 spec-bundle 包含
execution,则在将分布式意图映射到原生 SLURM/Pyxis 时,保留其顺序和语义。只暂存其校验和闭合的supporting_files。完整的通用生命周期和暂存约定见references/slurm-container-execution.md。 - 渲染
templates/slurm/singlenode.sbatch.tmpl— 替换所有@@<NAME>@@(JOB_NAME=$JOB_ID、NUM_GPUS、CPUS_PER_TASK、TIME、LOG_DIR、IMAGE、CONTAINER_MOUNTS=<RUNTIME_SUPPLIED_MOUNTS>、COMMAND=<bundle command reading the shared-storage spec>、SBATCH_EXTRA=账户/分区行、ENV_FILE=sidecar 路径或 留空、EXTRA_ENV=任意集群 NCCL 参数)→<job_dir>/sbatch/job_$JOB_ID.sbatch。 提交前进行 lint 和语法检查:redact_secrets.py lint <sbatch>必须 通过,且bash -n <sbatch>必须成功。 - 提交 + 记录为 RUNNING:
SLURM_ID=$(ssh $LOGIN "sbatch --parsable <job_dir>/sbatch/job_$JOB_ID.sbatch") "$BANK/scripts/tao_job_record.py" mark "$JOB_ID" --state RUNNING --backend-ref "$SLURM_ID"
跳过检查门禁或打开记录的提交没有 ID — 因此无法启动。
状态
# sacct ANNOTATES states ("CANCELLED by 12345") and truncates them to the
# default column width, so a cancelled job reads back as "CANCELLED+" and
# matches nothing in the table below — reporting UNKNOWN instead of CANCELED.
# Widen the column, take the first word, drop the truncation marker.
st=$(ssh $LOGIN "sacct -j $SLURM_ID -X -n -o State%30" | awk '{print $1}' | tr -d '+')
# (use squeue while the job is still PENDING; sacct lags briefly after submit)
| SLURM 状态 | 词汇 |
|---|---|
PENDING | PENDING |
RUNNING / COMPLETING | RUNNING |
COMPLETED | COMPLETE(确认 results_dir 中的 status.json) |
FAILED / TIMEOUT / OUT_OF_MEMORY | ERROR(区分基础设施错误与程序错误 → 重试,M6) |
NODE_FAIL / BOOT_FAIL | ERROR,err_class=ERR_INFRA(--requeue 会重新排队这些作业) |
CANCELLED / PREEMPTED / REVOKED | CANCELED |
| (未找到) | UNKNOWN |
原生子状态会随转换的 message 一并传递。按选定间隔轮询;
排队时间较长很正常 — 不要因耗时而停止。
日志
ssh $LOGIN "tail -n ${N:-200} <log_dir>/$JOB_ID-$SLURM_ID/main.out" # SLURM auto-creates the %x-%j subdir
取消
ssh $LOGIN "scancel $SLURM_ID"
"$BANK/scripts/tao_job_record.py" mark "$JOB_ID" --state CANCELED --source agent
将已终止的 SLURM 作业视为取消成功。
多节点(节点数 > 1)
相同的四个动词,提交时增加三项:
- 渲染
templates/slurm/multinode.sbatch.tmpl,而不是单节点模板——它是严格的超集(增加了--nodes/--wait-all-nodes和 rendezvous 代码块)。WORLD_SIZE表示节点数(这是 TAO 的误称);绝不要将其改为全局 rank 数。 - 先运行 NCCL 探测——在实际作业之前,用容器的 torchrun 运行一个开销很低的双节点 all-reduce(
scripts/nccl_allreduce_probe.py),超时时间约为 120 秒。在调用 torchrun 前,将 TAO rendezvous 值保存为TAO_NODE_COUNT=$WORLD_SIZE、TAO_GPUS_PER_NODE=$NUM_GPU_PER_NODE和TAO_NODE_RANK=$SLURM_PROCID;torchrun 会将标准的WORLD_SIZE覆盖为全局进程数。NCCL_PROBE_OK→ 继续。超时(collective 挂起)→ 在EXTRA_ENV中设置集群的 NCCL 参数并重新探测——在 CS-OCI-ORD 上,该参数为export NCCL_P2P_DISABLE=1(节点内 P2P 挂起),通常还会设置NCCL_SOCKET_IFNAME=eth0/NCCL_IB_DISABLE=1。按集群缓存可用的环境变量,以便后续作业跳过探测。还要满足gpus_per_node > 1才启用检测——在单节点有 2 个或更多 GPU 时也会触发 P2P 挂起。 - Tier-A Lustre、sidecar 凭证、记录和 lint 均保持不变。
Cosmos 后端防护措施
渲染 Cosmos 命令前,请阅读 references/cosmos-slurm-guardrails.md。其中定义了镜像暂存、planner 实例化、Framework 和 Cosmos-RL 启动约定、worker/runtime 要求,以及退出状态处理。
存储
使用共享文件系统 URI,而不是本地路径或 file:// 路径;对于远程后端,tao-core 会拒绝本地路径和 file:// 路径。
- Lustre 上由用户提供的数据集使用
lustre:///absolute/path。 - 微服务元数据中可能会出现
slurm://路径,并会在容器启动前转换为 Lustre 路径。
数据集根目录(模型技能会将其映射到所需文件)或直接使用 spec-key 路径均可。SSH 连接成功后、生成脚本前,从登录主机对每个必需的数据集路径执行 test -e;如果失败,请停止并要求提供正确路径或已暂存的数据,而不是生成会在第一个训练作业中失败的脚本。根目录模式与直接 spec 模式、后端详情和结果目录默认值,请参阅 references/slurm-ssh-credentials.md。
容器执行
tao-core 通过 Pyxis/Enroot 运行 TAO 容器:
- 将 spec、环境和云元数据的紧凑 JSON 文件暂存到
<job_dir>/specs、<job_dir>/env和<job_dir>/meta下。 - 在 GPU 作业之前,使用
srun -n1 -p <conversion_partition> enroot import将 Docker 镜像转换为缓存的 SQSH 镜像。这是每个镜像只需支付一次的开销,并非可选优化——请参阅下文的 在 GPU 分配之外获取镜像。 - 在
<job_dir>/sbatch/job_<job_id>.sbatch下写入 sbatch 脚本。 - 提交
sbatch --export=ALL <script>。 - 使用
srun --container-image=<image> --container-mounts=<RUNTIME_SUPPLIED_MOUNTS>运行容器。
接受的镜像格式:/path/to/image.sqsh、registry#image:tag、docker://registry#image:tag,以及普通的 registry/image:tag(需要时会转换为 Pyxis 格式)。SQSH 转换会按镜像名称缓存;对于 :latest 镜像,除非启用了 force_reconvert_latest,否则会复用缓存的 SQSH 镜像。
在 GPU 分配前获取镜像
从分配开始时起,GPU 就归你使用,而不是从计算开始时起。 训练前的任何操作——拉取镜像仓库中的镜像、转换镜像、获取数据集——都会占用空闲且计费的 GPU,并会被集群的 GPU 空闲回收器发现。首次拉取 TAO 镜像并进行 enroot 转换需要几分钟,这段时间足以导致任务被终止,也会产生不必要的费用。
因此,GPU 作业启动时,镜像必须已经是本地 .sqsh 文件。直接将 docker:// 或 registry#image:tag URI 传给 srun --container-image=,会让 Pyxis 在分配期间拉取并转换镜像——这正是需要避免的陷阱。先在 CPU 分区上转换一次,然后让后续所有作业都指向生成的文件:
# One-time per image, on CPU — costs no GPU time.
ssh $LOGIN "test -e <sqsh>" || \
ssh $LOGIN "srun --chdir=/tmp -n1 -c4 --mem=7200M \
-p <cpu_partition> -t <minutes> \
bash -c 'set -Eeuo pipefail
export TMPDIR=/tmp
export ENROOT_TEMP_PATH=/tmp/enroot-tao-\${SLURM_JOB_ID}
export SLURM_ENROOT_TEMP_PATH=\${ENROOT_TEMP_PATH}
mkdir -p \"\${ENROOT_TEMP_PATH}\"
cd /tmp
enroot import -o <sqsh> docker://<registry>#<image>:<tag>'"
# Every GPU job then references the file, never the registry.
srun --container-image=<sqsh> ...
数据也遵循同样的规则:提交前先将数据暂存到 Lustre(tier A),不要在分配期间获取。
CS-OCI-ORD 转换使用 cpu_long、4 个 CPU、7200M 内存、不独占节点、节点本地的 Enroot 临时路径,并且至少需要 120 分钟。执行参考记录了相关证据和 QOSGrpMemLimit 恢复约定。
部分转换会自动检测:通过 hsqs 魔数验证 SQSH,因此截断的文件会被拒绝,而不会被悄悄使用。转换只执行一次,之后会按镜像名称缓存。
转换失败时,绝不能回退到镜像仓库中的镜像。 看似方便的恢复方式——将 docker://… 传给 srun 并让 Pyxis 处理——会让拉取操作重新回到 GPU 分配期间,造成转换原本要避免的开销,而且恰好是在已经出现问题时发生。应将转换失败或文件截断视为致命错误:在 CPU 分区上修复后重新提交。
诊断:如果作业生成输出的速度异常缓慢,请检查 --container-image= 实际接收的内容。如果这里是镜像仓库 URI,而不是 .sqsh 路径,就说明拉取操作发生在 GPU 上。
监控和取消
- 调度器状态通过已存储的 SLURM 作业 ID 从
squeue/sacct获取;TAO 终端状态来自共享结果文件夹中的status.json。 - 启用聊天监控时,对于任何非终态作业(
PENDING、RUNNING或其他状态),都应按请求的间隔持续轮询。不要在经过固定时长(例如 30 分钟)后停止;共享 GPU 分区上的排队等待时间较长很常见。 - 启用聊天监控时,SLURM 作业仍处于非终态就不要发送最终回复。最终回复会导致脱离监控;仅当用户要求脱离/停止,或作业达到终态时,才使用最终回复。
- 通过 SSH 从
<job_dir>/slurm-logs/<slurm_job_name>-<slurm_job_id>/main.out和.err读取日志。 - 通过查询
backend_details.slurm_metadata.slurm_job_id获取作业 ID,并通过 SSH 运行scancel <slurm_job_id>取消作业。将作业不存在或已终止的情况视为取消成功。
状态映射:
PENDING->PendingRUNNING或COMPLETING->RunningCOMPLETED-> 检查status.jsonFAILED、BOOT_FAIL、DEADLINE、OUT_OF_MEMORY、NODE_FAIL-> 如果日志符合可重试的基础设施故障模式,则重试;否则为ErrorCANCELLED、PREEMPTED、REVOKED->CanceledTIMEOUT->ErrorSUSPENDED、STOPPED->Running(仍由调度器管理,之后可能恢复;原生子状态会出现在状态转换消息中——与 docker 的paused采用相同约定)
必需输入
在 SLURM 信息收集环节询问以下内容;完整的凭据列表、微服务架构的键和默认值请参阅 references/slurm-ssh-credentials.md。
- SLURM_USER(必需):登录节点的 SSH 用户名。
- SLURM_HOSTNAME(必需):用于故障转移的逗号分隔登录主机名。
- SLURM_PARTITION(必需):用于提交 GPU 作业的分区列表。打包的默认值为
polar,polar3,polar4,grizzly,这些分区均按 4 小时队列处理。 - SSH_KEY_PATH(首选,预期在启动前提供):用于非交互式公钥身份验证的私钥。进行问题排查时,优先询问此项;优先使用它,而非作为后备方案的
SSH_AUTH_SOCK代理套接字。 - SLURM_BASE_RESULTS_DIR(可选):共享文件系统基础路径;默认值为运行时提供并验证的共享存储根目录。
- SLURM_ACCOUNT(通常由站点策略要求):用于
#SBATCH --account的账户。
除非用户表示其站点要求提供账户、需要自定义结果根目录,或工作流无法在不覆盖默认值的情况下继续,否则不要在初始信息收集环节询问 SLURM_ACCOUNT 或 SLURM_BASE_RESULTS_DIR。
资源默认值
tao-core 中的默认值:
num_nodes:1num_gpus:4max_num_gpus_per_node:8cpus_per_task:16time_hours:4timeout_hours:3.8max_time_hours:4container_mounts:运行时提供的显式源路径到目标路径的挂载use_requeue:trueuse_sqsh:true
启动器必须使用打包的 4 小时作业时长和 3.8 小时子进程超时默认值,绝不能使用 12 小时。如果用户提供的 SLURM_TIME_HOURS 更长,请在提交前确认所选分区支持该时长。对于打包的默认分区列表 polar,polar3,polar4,grizzly,拒绝超过 4 小时的请求;只有在用户确实需要更长的作业时长时,才询问是否更换分区。
达到或超过 max_num_gpus_per_node 时,分配独占节点,并根据 GPU 总数计算节点数量。
多节点与重试
对于多节点作业(num_nodes > 1),渲染后的
templates/slurm/multinode.sbatch.tmpl 会设置 sbatch 指令,并导出
PyTorch 分布式 rendezvous 环境变量:WORLD_SIZE、NUM_GPU_PER_NODE、
NODE_RANK、MASTER_ADDR 和 MASTER_PORT(29500)。TAO 入口会读取
WORLD_SIZE + NUM_GPU_PER_NODE,并在内部构建 torchrun。Cosmos-RL 对
controller、policy 和 rollout worker 有特殊的多节点角色处理。
有关 NCCL 探测门控和按集群缓存环境变量,请参阅上文提交小节
### Multi-node (nodes > 1)。
SLURM 作业输入请使用 Lustre,而不是 S3。 作业一经派发,GPU 分配
便立即开始,因此如果脚本开头花很长时间从 s3:// 下载数据,就会消耗
分配时长,可能导致作业因 GPU 空闲而被终止,而且无论如何都会产生费用。
请先将训练数据暂存到共享文件系统中,并通过 lustre:///... 引用。对于
小型辅助输入(检查点、配置),可以预先从 S3/HF/NGC 获取,但不要用于
训练数据集。K8s/Brev 不受此调度器空闲限制约束。
发生基础设施故障(NODE_FAIL、BOOT_FAIL、NCCL 传输超时、CUDA 驱动程序
初始化失败、GPU/IB 链路中断、OOM-killer 回收节点、Xid 错误)时,请根据
日志判断故障属于基础设施还是程序,并在重新提交暂存的工作负载前,使用
--retry-of 创建新的重试记录(M6)。普通训练失败会立即显现,因此损坏的
规范不会消耗重试额度。默认通过 SLURM_USE_REQUEUE=true 启用
#SBATCH --requeue,因此在任何 Agent 级别的重新提交之前,SLURM 本身会在
NODE_FAIL 或抢占时重新排队作业;Cosmos 等工作负载约定可能要求使用
--no-requeue。
如果 sbatch --parsable 返回空响应或 SSH 断开,请视为情况不明:
通过完全匹配的作业名称进行核对,切勿盲目提交,并验证继承的节点排除设置。
所引用的执行指南定义了完整的决策表。有关多节点环境变量/sbatch 指令的
完整细节与表格、集群要求、完整的 Lustre 而非 S3 规则,以及故障模式检查
清单,请参阅 references/slurm-container-execution.md。
参考资料
references/slurm-ssh-credentials.md— 预检脚本、SSH/密钥设置、 enroot 凭据、完整凭据列表、后端详情、存储规则、 SSH 修复提示词。references/slurm-container-execution.md— 容器执行步骤、监控、状态映射、 取消、多节点详情、Lustre 而非 S3、重试、故障模式。references/slurm-preflight-storage.md— 扩展预检/存储说明。references/cosmos-slurm-guardrails.md— Cosmos Framework 和 Cosmos-RL 启动与状态防护措施。references/detailed-guide.md— 拆分参考资料的导航图。