PAYATHON 2026

Slurm 运行中的作业如何在任务结束后释放部分节点?

数据小陈

可以释放已完成任务所使用的部分节点。在给出的环境中,缩容失败的关键原因是待保留的 NodeList 遗漏了运行批处理脚本的 batch node。将这个节点和所有仍在运行的任务所用节点一起保留后,scontrol update ... NodeList=... 就能正常完成缩容。

这个结论适用于题目中已经验证的环境,不能据此保证所有 Slurm 版本和集群配置都允许以相同方式调整运行中的作业。

为什么任务结束了,节点仍不能直接释放?

脚本先通过 sbatch 申请 40 个节点,再通过多个 srun 启动作业步骤,也就是 job steps。某个 srun 结束,只表示对应步骤完成,整个作业的节点不一定已经归还。

批处理脚本本身也需要运行位置,也就是 .batch 步骤所在的 batch node。即使该节点上负责计算的 TaskN 已经完成,主脚本仍可能在这里执行监控循环和 wait。

因此,待保留的节点集合应为:

仍在运行的作业步骤所用节点 ∪ batch node

原来的循环只收集未完成任务的节点。batch node 上的计算任务结束后,这个节点就可能被排除,导致节点更新失败。

如何修改节点释放逻辑?

先查询 batch node:

sacct -j "${SLURM_JOB_ID}.batch" -o 'NodeList'

确认查询结果后,在每次执行节点更新前,将它加入 nodesToKeep。下面的片段用于替换原循环中的更新部分;前提是已有逻辑已经正确收集所有仍在运行的任务节点,并设置了 anyFinishedTasks。

if [ "$anyFinishedTasks" = true ]; then
    batchNode=$(sacct -n -j "${SLURM_JOB_ID}.batch" -o 'NodeList%100')
    batchNode=${batchNode//[[:space:]]/}

    if [ -z "$batchNode" ]; then
        printf 'Cannot determine batch node; skipping resize.\n' >&2
    else
        # Remove the trailing separator left by the collection loop.
        nodesToKeep=${nodesToKeep%,}

        # Always retain the node running the batch script.
        nodesToKeep="${nodesToKeep:+${nodesToKeep},}${batchNode}"

        scontrol update \
            jobid="${SLURM_JOB_ID}" \
            NodeList="$nodesToKeep"
    fi
fi

这段代码保留了原脚本使用的 NodeList%100 输出宽度。使用前需要确认节点名称或节点表达式没有被截断;如果输出不完整,应调整查询格式后再执行更新。整理节点集合时也应去除重复节点。

如果原环境还需要加载 slurm_job_${SLURM_JOB_ID}_resize.sh,应在节点更新成功且脚本确实存在时执行。它不能代替保留 batch node 的逻辑。

为什么改用 NumNodes 仍然报错?

NumNodes 只表达希望保留的节点数量,无法指定哪些节点必须留下。即使算出了 40-5*[已完成任务数],也无法确保保留 batch node 和运行中步骤所用的节点。

下面的报错与作业状态及该环境接受的更新方式有关:

Job is no longer pending execution for job 1016205

现有信息没有包含 Slurm 版本、集群配置或更完整的诊断结果,无法进一步确定 NumNodes 在该环境中的具体限制。把整数改成范围也没有解决已观察到的问题。在这个案例中,已有验证支持显式更新 NodeList,并始终包含 batch node。

执行缩容前还要检查什么?

  • 确认步骤确实结束。原循环中的三引号内容只是占位表达,不能直接用作 Bash 的任务状态检查逻辑。
  • 确认步骤 ID。Task0 等程序名称并不保证对应 .0 等步骤编号,应以实际启动得到的 job step ID 为准。
  • 保留全部运行中步骤的节点。查询不到节点、输出为空或状态尚未确认时,应跳过此次缩容,避免提交不完整的列表。
  • 检查更新结果。scontrol update 失败后,应记录报错并保留当前分配,不要继续按缩容成功处理。

所有计算任务结束后,让监控循环退出,再由批处理脚本正常结束。仍被保留的 batch node 会随整个作业结束而归还,无需在脚本运行期间强行释放。

备注:内容仅供参考。