我的 IT 部门善意地为我设置了一个带有 Slurm 的 Linux 虚拟机,我正在学习命令。我稍微改变了数字,但假设有 2 个节点,每个节点有 5 个核心/CPU(我认为它们在这里是相同的?)。我想运行一个函数 6 次独立迭代,每次迭代 3 个子任务。前 2 个子任务 (a, b) 可以并行运行,但最后一个 (c) 需要前 2 个子任务完成。为简单起见,我们可以说每个子任务需要 1 分钟。
我们还可以说我开始设置 A 并进行迭代 1-6。但后来我意识到我想以更高的优先级运行集合 B 迭代 7-14,并立即开始下一步。在这种情况下,我希望在第 1 分钟内完成集合 A 中 5 次迭代的子任务 a 和 b。对于第 2 分钟,我希望在集合 B 中完成 5 次迭代的子任务 a 和 b。第 3 分钟我希望完成 B 的最后 8 个子任务以及 A 中的 2 个子任务。第 4 分钟将是 A 的最后 6 个子任务。
这可能吗?我该怎么办?
下面是A MWE,但是当我运行 top
命令时,刚开始
A,我看到某些进程的 CPU 使用率为 100%,而其他进程则为 50%。对于 50% 的进程,总运行数量多于核心数量。我希望脚本完成任务并等待 CPU 空闲后再开始下一个任务,因为我认为这样可以更快地完成迭代。但在此示例中,即使在 50% 的情况下,运行时间也始终为 2 分钟,这可能是由于
stress
命令的性质所致?由于某种原因,所有迭代也同时开始和结束。
我运行的命令
./test_main.sh
test_main.sh
的内容
#!/bin/bash
rm -rf 'out'
mkdir -p 'out/'
for i1 in {1..6}; do #Changed to 7..14 for B
printf -v i_str "%03d" $i1 #add zero-padding
sbatch ./test_sub.sh "$i_str"
done
以下
test_sub.sh
的内容。我尝试过使用 --hint=nomultithread
、--cpus-per-task=1
和 --ntasks-per-node=5
。在 srun
命令中,我尝试过使用和不使用 --exclusive
。
#!/bin/bash
#
#SBATCH --job-name setA ## name that will show up in the queue. Change for set B
#SBATCH --output slurm-%j.out ## filename of the output; the %j is equal to jobID
#SBATCH --nodes=2 ## Number of nodes
#SBATCH --oversubscribe ## Letting multiple jobs run concurrently
#SBATCH --partition=mypartition ## the partitions to run in (comma separated).
#SBATCH --nice=10000 ## Change to a smaller value for set B
in_dir=$1
run_s="$SECONDS" #start a timer
work_dir=$PWD
mkdir -p 'out/'$in_dir
cd 'out/'$in_dir
# Save some tracking info
hostname > example.out #always the name of the primary node. Not important to my task though
echo '('`date`')' >> example.out
srun -N1 -n1 --exclusive "$work_dir"/test_sub2.sh 'alpha' &
srun -N1 -n1 --exclusive "$work_dir"/test_sub2.sh 'beta' &
wait #wait for subprocess alpha and beta to finish
echo '('`date`')' >> example.out
# Can now run gamma
srun -N1 -n1 --exclusive "$work_dir"/test_sub2.sh 'gamma' &
wait
# Save additional tracking info after gamma finishes
echo '('`date`')' >> example.out
loop_rt=$( echo " scale = 2; ( "$SECONDS"- "run_s" ) / 60 " | bc )
echo "$loop_rt" >> example.out #Runtime
内容
test_sub2.sh
#!/bin/bash
greekLtr=$1
hostname > "$greekLtr".out
echo '('`date`')' >> "$greekLtr".out
stress --cpu 1 --timeout 60
echo '('`date`')' >> "$greekLtr".out
在我的调度下的 slurm.conf 文件中,我有
# SCHEDULING
SchedulerType=sched/backfill
SelectType=select/cons_tres
SelectTypeParameters=CR_CPU
对类似问题的指出也将不胜感激!谢谢!
我在这上面花了太多时间,我想我已经明白了。我没有尝试在一个作业中依赖 3 个 srun 任务,而是启动多个 sbatch 作业,每个作业有 1 个 srun 任务,并使它们相互依赖。下面的一些组合有效。
在我的 slurm.conf 文件中,我从 CR_CPU 更改为 CR_CPU_Memory。对于每个节点,我还添加了 RealMemory=16000(实际值来自在头节点上运行
slurm -C
)。然后我以root身份运行
systemctl restart slurmctld
scontrol reconfigure
我修改了
test_main.sh
并添加了对其他作业 ID 的依赖关系。
#!/bin/bash
# Set nice level
n_main=1000 #Decrease this for set B
n_dep=$(($n_main - 10))
mkdir -p 'out/'
ltr_ary=('alpha' 'beta' 'gamma')
for i1 in {1..6}; do #Changed to 7..14 for B
printf -v i_str "%03d" $i1 #add zero-padding
J_IDS='' #Previous job IDs in format ':42:43'
i2=0
for greekLtr in "${ltr_ary[@]}"; do
i2=$(($i2+1))
if [ "$i2" -lt "${#ltr_ary[@]}" ]; then
# Not the last one
out_txt=`sbatch --nice="$n_main" ./test_sub.sh "$i_str" "$greekLtr"`
else
out_txt=`sbatch --nice="$n_dep" --dependency=afterok"$J_IDS" ./test_sub.sh "$i_str" "$greekLtr"`
fi
job_ID=${out_txt##* } #get the job ID number after the final space
J_IDS="$J_IDS"':'"$job_ID"
done #end loop over greek letters
done #end loop over number iterations
修改为
test_sub.sh
为
#!/bin/bash
#
#SBATCH --job-name setA ## name that will show up in the queue. Change for set B
#SBATCH --output /home/username/slurmlogs/slurm-%j.out ## filename of the output; the %j is equal to jobID
#SBATCH --nodes=1 ## Number of nodes
#SBATCH --ntasks-per-node=1 ## Limiting number of tasks and hence CPU per node
#SBATCH --mem=3000M ## Don't give all memory to just 1 CPU
#SBATCH --cpus-per-task=1 ## Each task only needs 1 CPU
#SBATCH --partition=mypartition ## the partitions to run in (comma separated).
in_dir=$1
greekLtr=$2
work_dir=$PWD
mkdir -p 'out/'$in_dir
cd 'out/'$in_dir
# Could not figure out how to get SBATCH to not overload CPUs without srun and --exclusive...
srun -N1 -n1 --exclusive --mem-per-cpu=3000M "$work_dir"/test_sub2.sh "$greekLtr" &
wait
我保持
test_sub2.sh
不变。
我通过在设置A后立即开始设置B来验证这是否按预期工作。第一分钟后,我在
squeue
中观察到 B 作业已启动,而其余 A 作业则处于待处理状态。 CPU 使用率似乎最大化,而没有在任务之间分配。
这似乎有效,但请稍等一下接受我自己的答案,以防有更优雅的解决方案。