批处理作业的分配时间可以在slurm的sbatch命令上指定。例如,以下请求为1天3分10秒:
$ sbatch -t 1-0:3:10 test.sh
我的脚本需要知道它将运行多长时间,以便它可以在终止之前保存所有数据。sbatch手册页上列出的可用于作业的环境变量不包括分配时间限制。
我如何从脚本中确定这一点?
现在,我向队列管理器询问当前作业的时间限制:
#!/bin/sh
squeue -j $SLURM_JOB_ID -o "%l"
这给了我们
TIME_LIMIT
1-00:04:00
我使用以下代码解析输出:
#!/bin/bash
TIMELIMIT=`squeue -j $SLURM_JOB_ID -o "%l" | tail -1`
echo Time limit $TIMELIMIT
if [[ $TIMELIMIT == *-* ]]; then
IFS='-' read -ra DAYS_HOURS <<< $TIMELIMIT
DAYS=${DAYS_HOURS[0]}
PART_DAYS=${DAYS_HOURS[1]}
else
DAYS=0
PART_DAYS=$TIMELIMIT
fi
if [[ $HOURS == *:*:* ]]; then
IFS=':' read -ra HMS <<< $PART_DAYS
H=${HMS[0]}
M=${HMS[1]}
S=${HMS[2]}
else
IFS=':' read -ra HMS <<< $PART_DAYS
H=0
M=${HMS[0]}
S=${HMS[1]}
fi
SECONDS=`echo "((($DAYS*24+$H)*60+$M)*60+$S)" | bc`
echo Time limit: $SECONDS seconds
HOURS=`echo "scale=3;((($DAYS*24+$H)*60+$M)*60+$S)/3600." | bc`
echo Time limit: $HOURS hours
这给了我们
Time limit 1-00:04:00
Time limit: 86404 seconds
Time limit: 24.001 hours
有没有更干净的方法来做这件事?
发布于 2019-03-16 18:10:07
几件事。
如果使用proctrack/cgroup,则可以捕获在时间限制到期时发送的SIGTERM信号。这为您提供了一个可配置的保存状态的时间量;在slurm.conf中配置的KillWait秒后发送SIGKILL。但是,如果您使用的是proctrack/linuxproc,就很难做到这一点,因为它会将SIGTERM发送到所有进程,而不仅仅是bash脚本。如下所示:
#!/bin/bash
function sigterm {
echo "SIGTERM"
#save state
}
trap sigterm TERM
srun work.sh &
# This loop only breaks when all subprocesses exit
until wait; do :; done
如果您以前从未在bash中捕获过信号,这可能会很难做到。使用proctrack/cgroup,SIGTERM被发送到每个作业步骤的主进程和批处理脚本。如上所述,work.sh还必须捕获SIGTERM。同样在上面,bash并不会在子进程结束之前捕获信号,除非您对它们进行后台处理;因此会出现'&‘and wait循环。
如果您确实希望将timelimit传递到作业中,则可以使用环境变量。
sbatch --export=ALL,TIMELIMIT=1-0:3:10 -t1-0:3:10 test.sh
令人恼火的是,您必须指定两次时间限制。
用squeue
查询控制器并不是一个糟糕的解决方案。然而,在规模上,数千个查询控制器的作业可能会影响性能。请注意,您可以使用--noheader
标志而不是每次都打印TIME_LIMIT,而不是使用tail
。
基本上,这就是设计KillWait的目的,所以你应该考虑使用它,除非你因为某种原因不能使用它。https://slurm.schedmd.com/slurm.conf.html
最好的答案可能是对sbatch
使用--signal
选项。这允许您在时间限制结束之前的一定时间内向您的作业发送可配置信号。
sbatch --signal=B:USR1@120 myscript.sh
上面的示例在作业结束前大约2分钟将USR1发送到批处理脚本。如手册页中所述,分辨率为60秒,因此信号最多可以提前60秒发送。
https://stackoverflow.com/questions/55191098
复制相似问题