Slurm在作业运行过程中释放部分节点,使它们成为该作业内部的子作业/任务,直到作业结束
我有很多任务要执行。我可以独立提交每个任务,但我所用集群的排队系统会优先处理较大的作业,因此大任务常常需要等待数月。
相反,我开始提交更大的作业,其中每个作业随后会启动若干子作业或任务,以并行方式运行。
这都运行得很好。然而,各个任务完成所需的时间差异可能很大,通常在4到16小时之间,而且我没有一个好办法能够事先判断每个任务需要多久。
这意味着大量节点会空闲数小时,数据设施的管理层对此并不感到高兴。
我想做的是在每个任务完成后释放它所运行的节点。我尝试使用 scontrol update 在任务运行时更新作业,但没有成功。
当前用于启动作业的脚本大致如下:
#!/bin/bash
#SBATCH -J thisJobName
#SBATCH --nodes=40
#SBATCH --ntasks-per-node=128
#SBATCH -t 24:00:00
#SBATCH --mem=0
source /path/to/load_modules
srun --nodes=5 --exclusive --ntasks-per-node=128 Task0 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task1 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task2 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task3 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task4 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task5 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task6 &
srun --nodes=5 --exclusive --ntasks-per-node=128 Task7 &
wait
我尝试在任务完成后释放节点的方法大致如下:
while true; do
nodesToKeep=""
anyFinishedTasks=false
anyRunningTasks=false
# Check if any tasks have finished. Keep track of the nodes still in use
for task in $(seq 0 7); do
"""Check if task is completed"""
if [ """task is not completed""" ]; then
# Find nodes this task is running on
taskNodes=$(sacct -n -j ${SLURM_JOB_ID}.${task} -o 'Nodelist%100')
# Remove spaces from output
taskNodes=${taskNodes//" "/""}
nodesToKeep="${nodesToKeep}${taskNodes},"
anyRunningTasks=true
else
anyFinishedTasks=true
fi
done
# if no tasks are still running, break out of the loop
if [ $anyRunningTasks = false ]; then
break
fi
### -------------------------------------------
### THIS IS THE IMPORTANT PART THAT DOESNT WORK
### -------------------------------------------
# If any tasks have finished, Update the node list for the job to not include the ones no longer in use
if [ $anyFinishedTasks = true ]; then
scontrol update jobid=${SLURM_JOB_ID} NodeList=$nodesToKeep
. ./slurm_job_${SLURM_JOB_ID}_resize.sh
fi
### ------------------------------------------
### END OF THE IMPORTANT PART THAT DOESNT WORK
### ------------------------------------------
# Check again in 5 more minutes
sleep 300
done
wait
然而,这会给我一个错误信息,说是
Invalid node name specified for job 1016205
Trying to run a test where i allocate an extra node which never gets assigned to a task, I have found that the extra node can be deallocated in this way, so the error is not in the way i am listing the nodes.
如果不使用 scontrol update jobid=${SLURM_JOB_ID} NodeList=$nodesToKeep 而改用 scontrol update jobid=${SLURM_JOB_ID} NumNodes=${numberOfNodesToKeep}(其中 numberOfNodesToKeep 只是40-5*[number of finished tasks]),我会得到以下错误消息
Job is no longer pending execution for job 1016205
对一个问题的另一个回答这里建议 scontrol update jobid=${SLURM_JOB_ID} NumNodes=${numberOfNodesToKeep}-${numberOfJobsToKeep} 能工作,但结果仍然一样。
我不知道为什么这些选项都不起作用,我已经快想不出主意了。
编辑:已解决
我找到了问题。一台节点被分配为从中运行脚本的“批处理节点”。该节点不能被回收。因此,用 sacct -j ${SLURM_JOB_ID}.batch -o 'NodeList' 找出该节点,并确保该节点始终保留在要保留的节点列表中,这样一切就能顺利工作。批处理节点因此保持分配,即使在该节点上运行的任务完成,但只有一个单独的节点在大多数时间处于空闲状态,远比有20个空闲节点要好。希望如果有人在某个时候遇到同样的问题,这能有所帮助。
解决方案
我找到了问题。一台节点被分配为从中运行脚本的“批处理节点”。这台节点不能被回收。因此,用 sacct -j ${SLURM_JOB_ID}.batch -o 'NodeList' 找出该节点,并确保该节点始终保留在要保留的节点列表中,这样一切就能顺利工作。批处理节点因此保持分配,即使在该节点上运行的任务完成,但只有一个单独的节点在大多数时间处于空闲状态,远比有20个空闲节点要好。希望如果有人在某个时间遇到同样的问题,这能有所帮助。