如何配置Slurm作业数组依赖:前序数组任务启动后再调度
嘿,我来帮你搞定这个Slurm数组任务的依赖配置!你想要实现的是数组里的每个任务必须等前一个任务启动后才能进入调度队列,对吧?刚好Slurm有对应的方法来实现这个需求,不过不能直接在你原来的提交脚本里硬写依赖参数,得稍微调整下提交方式,下面给你两种可行的方案:
方案1:循环提交链式依赖任务(适合大规模数组)
因为Slurm的SLURM_ARRAY_TASK_ID是在任务运行时才会被赋值的,提交脚本的时候没法直接引用它来指定前一个任务的ID,所以我们可以分步骤提交:先启动第一个任务,然后逐个提交后续任务,每个都依赖前一个任务的启动状态。
首先,先提交数组的第一个任务,记下它的完整任务ID:
sbatch --account=******* --array=1 --time=00:05:00 --mem-per-cpu=256M your_script.sh
执行后会返回类似Submitted batch job 12345的信息,那第一个任务的完整ID就是12345_1。
然后用循环提交剩下的任务,每个任务都设置依赖前一个任务的启动:
prev_task_id=12345_1 for i in {2..1000}; do # 提交当前任务,依赖前一个任务启动 submit_output=$(sbatch --account=******* --array=$i --time=00:05:00 --mem-per-cpu=256M --dependency=after:$prev_task_id your_script.sh) # 提取当前任务的ID,格式是 主ID_任务号 current_job_id=$(echo $submit_output | awk '{print $4}') prev_task_id="${current_job_id}_${i}" done
这里的--dependency=after:$prev_task_id就是关键:它告诉Slurm,当前任务必须等prev_task_id对应的任务已经启动之后,才能进入调度队列。如果你的实际需求是要等前一个任务完成(不管成功失败)再启动,就把after:换成afterany:;如果只想要前一个任务成功完成才继续,就用afterok:。
方案2:用包装脚本简化提交流程
如果你不想手动敲命令,也可以写一个提交包装脚本submit_array.sh,一键搞定所有任务的提交:
#!/bin/bash # 先提交第一个任务 first_submit=$(sbatch --account=******* --array=1 --time=00:05:00 --mem-per-cpu=256M job_runner.sh) first_task_id=$(echo $first_submit | awk '{print $4}_1') # 循环提交剩余任务 for task_num in {2..1000}; do current_submit=$(sbatch --account=******* --array=$task_num --time=00:05:00 --mem-per-cpu=256M --dependency=after:$first_task_id job_runner.sh) current_job_id=$(echo $current_submit | awk '{print $4}') first_task_id="${current_job_id}_${task_num}" done
然后把你原来的执行逻辑放到job_runner.sh里:
#!/bin/bash ./job.sh >output$SLURM_ARRAY_TASK_ID.txt exit
这样只要运行./submit_array.sh,就能自动按顺序提交所有1000个任务,每个都等前一个启动后再调度。
为什么原来的脚本没法直接写依赖?
简单说,你原来的脚本里的--dependency=???????没法直接填内容,因为SLURM_ARRAY_TASK_ID这个变量只有当任务真正运行的时候,Slurm才会给它赋值。提交整个数组的时候,这个变量还不存在,所以没法用它来指定前一个任务的ID,必须通过动态提交的方式逐个设置依赖关系。
内容的提问来源于stack exchange,提问作者Dean Eaton

