MiniMax logo

Skill

hpc-slurm

submit and monitor Slurm HPC jobs

Published by MiniMax Updated Aug 21
Covers Automation CLI Deployment Engineering

Description

当用户需要向 Slurm 集群提交计算作业,说"提交集群任务""写个 sbatch 脚本""作业还在排队吗""批量跑一组参数""作业超时被杀了""GPU 作业怎么交"时使用。本技能规定 Slurm 集群的统一操作规程:sbatch 脚本模板(分区/时长/内存/GPU 指令 + set -euo pipefail + 环境导出 + 结束自动 rsync 产物)、squeue/sacct 状态查询口径、数组任务批量提交、超时与重排队策略、产物抓回与 record_run 登记。同义触发场景:Slurm、HPC、集群、超算、排队、批处理、job array、机时。连接与主机认知纪律沿用 remote-compute(别名、画像合同),本技能只规定作业生命周期。

SKILL.md

hpc-slurm:Slurm 集群作业规程

目的

Slurm 集群的算力是排队共享的:脚本写错浪费机时,资源虚报挤占同门队列,作业跑完不抓回等于没跑。本技能规定作业生命周期的五个环节:

  1. 提交前:脚本模板化,资源申请有依据;
  2. 队列中:状态查询口径统一,不盲目刷屏;
  3. 批量时:数组任务替代循环提交;
  4. 异常时:超时与失败有明确的重排队策略;
  5. 完成后:产物自动 rsync 抓回 + record_run 登记。

前置约束:连接一律走 remote-compute 的别名与 ControlMaster 纪律;目标主机的分区、GPU、配额信息以 .openscience/hosts/<alias>.yaml 画像为准——画像没有的信息(如分区名)先探测(sinfo)再写进脚本,不臆造。

前置检查

  1. 画像 scheduler: slurm 已确认;画像缺失或过期时先按 remote-compute 第 2 节探测。
  2. 查可用分区与节点:ssh <alias> 'sinfo -o "%P %a %l %D %N"',把目标分区、单作业时长上限写进画像 notes。
  3. 提交计算作业消耗机时与队列资源,属 guardrail 第 8 条危险操作:首次提交前向用户说明作业规模(核数、时长、分区、预计机时)并获得确认;数组任务说明总任务数。
  4. 数据与代码已同步到远程(rsync 上传),脚本内路径全部是远程路径。

1 · sbatch 脚本模板

作业脚本放本地 scripts/slurm/<job-name>.sbatch(纳入工作区管理),模板:

#!/bin/bash
#SBATCH --job-name=cycle-fit        # 短而可读,squeue 里认得出
#SBATCH --partition=gpu             # 以画像/sinfo 为准,不臆造分区名
#SBATCH --time=08:00:00             # 预留 20-50% 余量,不写分区上限
#SBATCH --mem=32G
#SBATCH --cpus-per-task=8
#SBATCH --gres=gpu:1                # 无 GPU 作业删掉此行;型号需求以画像 gpu_summary 为准
#SBATCH --output=%x-%j.out          # <job-name>-<jobid>.out,便于归档
#SBATCH --error=%x-%j.err

set -euo pipefail                   # 任何命令失败立即终止作业,不带着错误继续跑

# ---- 环境导出(三选一,与画像 notes 中该集群的习惯一致)----
# module load cuda/12.2 anaconda/2024.02 && source activate myenv
# source "$HOME/.venv/bin/activate"
export PYTHONUNBUFFERED=1           # 日志实时可见,便于中途检查

# ---- 任务本体 ----
JOB_DIR="$HOME/runs/${SLURM_JOB_NAME}-${SLURM_JOB_ID}"
mkdir -p "$JOB_DIR"
cd "$JOB_DIR"
python3 "$HOME/code/analyze_cycle.py" --seed 42 --out "$JOB_DIR"

# ---- 结束自动 rsync 产物回本地工作区 ----
# 仅在登录节点可反向访问本地时可用;多数集群不通,改用完成后手动抓回(第 5 节)
rsync -avz "$JOB_DIR/" "<local-alias>:<工作区路径>/results/${SLURM_JOB_NAME}-${SLURM_JOB_ID}/" \
  || echo "WARN: auto rsync failed, fetch manually" >&2

echo "JOB_DONE $(date -Is)"

模板纪律:

  1. set -euo pipefail 不可省:没有它,中间步骤失败后作业继续跑,产出半截结果还显示"完成"。
  2. 资源申请按画像与实际需求填,不虚报(虚报挤占队列、拖长全组排队),也不少报(OOM/超时被杀浪费机时)。
  3. 产物目录名带 ${SLURM_JOB_ID},同一脚本多次提交互不覆盖。
  4. 环境导出让作业自包含:不依赖登录节点的交互式 shell 状态。

2 · 状态查询:squeue / sacct

统一口径,避免凭印象判断:

ssh <alias> 'squeue -u $USER'                      # 在队作业:R=运行 PD=排队
ssh <alias> 'sacct -j <jobid> --format=JobID,JobName,State,Elapsed,MaxRSS,ExitCode'

解读要点:

  1. PD(排队)看 squeueNODELIST(REASON)Resources/Priority 是正常排队;ReqNodeNotAvail 等多为资源请求超分区配置,应改脚本而不是干等。
  2. 作业结束后一律 sacct 确认 StateExitCodeCOMPLETED + 0:0 才算成功;TIMEOUT/OUT_OF_MEMORY 按第 4 节处理。
  3. 不轮询刷屏:查询间隔不低于分钟级;长作业用 run-monitor 思路"提交后离开,定期回来查",不让人机空等。

3 · 批量作业:数组任务

同脚本多参数(多 seed、多数据分片)一律用 job array,禁止 for 循环逐条 sbatch:

#SBATCH --array=0-99%10            # 100 个任务,最多同时 10 个(%10 限制并发,别挤爆队列)

python3 "$HOME/code/analyze.py" --seed "$SLURM_ARRAY_TASK_ID" \
    --out "$HOME/runs/${SLURM_JOB_NAME}-${SLURM_ARRAY_JOB_ID}/task-${SLURM_ARRAY_TASK_ID}"

纪律:

  1. 每个数组元素产物独立目录(带 task id),互不覆盖;
  2. 首次跑大批量前先用 --array=0-2 小规模试跑,确认单任务资源估算正确,再提交全量;
  3. 抓回时按 ${SLURM_ARRAY_JOB_ID} 整目录 rsync,record_run 一条登记、note 写数组范围与失败元素。

4 · 超时与重排队策略

  1. TIMEOUT:先查日志判断是"差一步"还是"差很远"。差一步:加大 --time 重交;差很远:检查是否有死循环或规模估计错误,修复后重交。同一作业连续两次 TIMEOUT 不得原样重交,必须先改东西。
  2. OUT_OF_MEMORY:按 sacctMaxRSS 实测值上调 --mem(留 20% 余量)重交。
  3. FAILED(非零退出):读 .err 定位,修复后重交;失败作业同样登记 provenance(paths 指向抓回的日志)。
  4. 可断点续算的任务:脚本内支持 checkpoint(存在则续跑),超时重交即自动续算;长任务优先设计成可续算的。
  5. 重排队是新的资源消耗:批量重交前向用户说明失败原因与新增机时。

5 · 产物抓回与 record_run

自动 rsync(模板末尾)不通时,完成后手动抓回:

rsync -avz <alias>:~/runs/<job-name>-<jobid>/ results/<job-name>-<jobid>/
python <插件包路>/skills/provenance-record/scripts/record_run.py \
  --path results/<job-name>-<jobid>/ \
  --tool "slurm job <jobid> (<job-name>.sbatch)" \
  --note "分区 <p>,8 核 32G 1×GPU,实际耗时 <Elapsed>,ExitCode 0:0,节点 <NodeList>"

不记录的运行等于不存在:note 里作业号、sacct 的 Elapsed/ExitCode/NodeList 缺一不可;远程环境版本(module list 摘要)有条件就附在 note 或抓回的日志里。

6 · 经 run_task 登记 Slurm 作业

sbatch 提交成功、拿到 jobid 后,立即把"盯这个作业"登记成一个本地 Run——用 run-monitor 的 Run 抽象统一管理本地与远程长任务:Run 只记录"任务叫什么、怎么查状态、查到了什么",不关心任务跑在本机还是集群:

python <插件包路>/skills/run-monitor/scripts/run_task.py \
  start --name <job-name>-<jobid> \
  --tag slurm --tag <cluster> \
  --cmd "ssh <alias> 'sacct -j <jobid> --format=State -n | head -1'"

模式说明:

  1. 登记即交还:start 把这条状态查询命令放到后台执行并立即返回,会话不空等;run.json 的 cmd 字段留下"当时用哪条命令查的",口径与第 2 节一致,tags 与 note 一并落盘。
  2. 轮询即重跑:想看最新状态时同名再 start 一次(已 exited 的 run 允许被新 start 覆盖,日志随之重写),然后 tail 看这次查到的 State;查询间隔不低于分钟级的纪律不变,不写忙等循环。
  3. tags 即检索口径--tag slurm --tag <cluster>run_task list 把集群作业与本地任务一眼分开;多集群、多作业并发时按 tag 认作业,不靠记忆。补充背景(分区、资源、预计时长)用 --note 写一句。
  4. 终态与抓回纪律不变:sacct 显示 COMPLETED/FAILED/TIMEOUT 后,产物抓回与 record_run 登记仍按第 5 节执行,一个字不改;Run 替代的是"人机空等",不替代 provenance。

输出模板

## Slurm 作业已提交(<job-name> @ <alias>)

- jobid:<id>,分区:<p>,资源:<核/内存/GPU/时长>
- 预计排队:<squeue 观察>;查询:ssh <alias> 'squeue -j <id>'
- 完成后:自动 rsync 至 results/<job-name>-<id>/ 或按第 5 节手动抓回 + record_run

本技能不做什么

  • 不探测主机与管连接:别名、ControlMaster、画像合同、失败分支一律沿用 remote-compute,本文件不重复。
  • 不保证队列策略最优:分区选择、机时估计给建议,最终以用户所在集群的实际规定(画像 notes)为准。
  • 不自动 kill 作业:scancel 只建议不执行,除非用户当场明确确认(影响共享队列状态)。
  • 不管非 Slurm 调度器:PBS/LSF 语法不同,本规程不套用;画像 scheduler 非 slurm 时按 remote-compute 的交互式方案。
  • 不替用户盯梢:提交后告知查询命令即交还控制权,长周期作业由用户按节奏回来查(或按第 6 节用 run_task 登记)。

收尾与下一步

  • 作业成功后:确认 rsync 完成、record_run 已登记、产物按契约归位(latest 刷新)。
  • 批量作业:核对数组元素完整性(100 个任务 100 个产物目录),缺的按第 4 节补交。
  • 结论进论文前:sbatch 脚本 + sacct 摘要 + 产物一并进 evidence-capsule 冻结。
  • 作业失败:登记失败记录后诊断,诊断结论写进下一条 provenance note,形成可追溯的试错链。

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.