【问题标题】:How can I run this simple for loop in parallel bash?如何在并行 bash 中运行这个简单的 for 循环?
【发布时间】:2021-08-21 13:10:42
【问题描述】:

我正在尝试使用不同的参数多次运行 Rscript,并且我正在使用 bash 脚本来执行此操作(尝试在 R 中使用 foreach 和 doParallel 之类的东西并行运行它时出现错误,但这不是这里有问题)。

我打算用$sbatch script.sh(在 hpc 上)调用的脚本如下所示:

#!/usr/bin/bash

#SBATCH --time=48:00:00
#SBATCH --mem=10G
#SBATCH --mail-type=END
#SBATCH --mail-type=FAIL
#SBATCH --mail-user=my@mail.com

cd my_dir

for a in 1 2
do
for b in 1 2 3 4
do
for c in 1 2 3
do
for d in 1 2 3 4
do
for e in 5 10 15 20 30 40 50 75 100 200 300 400 500 750 1000 1250 1500 1750 2000
do
Rscript /hpc/someRscript.R $dist $rlen $trans $meta $init &
done
done
done
done
done

echo done

命令$sbatch script.sh 导致我在大约 40 秒后收到一封电子邮件,告诉我它完成了。我怀疑使用 & 符号是这里的不法行为者。我认为它试图同时做所有事情,这会使计算节点过载。

有没有一种简单的方法可以把它变成一个数组作业?还是有更好的方法让我并行运行?

【问题讨论】:

  • 如果您希望限制并行操作(例如,基于可用资源),那么您可能需要查看 a) GNU parallel、b) xargs / -P 或 c) 自行操作通过手动计算后台启动的作业数量加上wait -n的使用来编写代码;谷歌搜索这些项目中的任何一个都应该会在 stackoverflow(或其姊妹网站)上获得相当多的点击率

标签: r bash parallel-processing slurm


【解决方案1】:

要使您的脚本正常工作,您需要

  1. 要么使用变量名称abc 等,要么使用$dist$rlen$trans$meta$init,但不能同时使用两者
  2. wait 结束脚本,否则 Slurm 会认为您的脚本已完成

所以:

#!/usr/bin/bash

#SBATCH --time=48:00:00
#SBATCH --mem=10G
#SBATCH --mail-type=END
#SBATCH --mail-type=FAIL
#SBATCH --mail-user=my@mail.com

cd my_dir

for dist in 1 2
do
for rlen in 1 2 3 4
do
for trans in 1 2 3
do
for meta in 1 2 3 4
do
for init in 5 10 15 20 30 40 50 75 100 200 300 400 500 750 1000 1250 1500 1750 2000
do
Rscript /hpc/someRscript.R $dist $rlen $trans $meta $init &
done
done
done
done
done
wait
echo done

现在的一个问题是,这将创建 1824 个进程并尝试同时运行它们。这将是非常低效的。因此,您应该使用srun 在可用数量的 CPU 上“微调度”所有这些进程。请注意,您可能需要使用 --ntasks 显式请求一定数量的 CPU。

#!/usr/bin/bash

#SBATCH --time=48:00:00
#SBATCH --mem=10G
#SBATCH --mail-type=END
#SBATCH --mail-type=FAIL
#SBATCH --mail-user=my@mail.com
#SBATCH --ntasks=<SOME NUMBER>

cd my_dir

for dist in 1 2
do
for rlen in 1 2 3 4
do
for trans in 1 2 3
do
for meta in 1 2 3 4
do
for init in 5 10 15 20 30 40 50 75 100 200 300 400 500 750 1000 1250 1500 1750 2000
do
srun -n 1 -c 1 --exclusive Rscript /hpc/someRscript.R $dist $rlen $trans $meta $init &
done
done
done
done
done
wait
echo done

此外,如果 GNU Parallel 可用,您可以将脚本简化为

#!/usr/bin/bash

#SBATCH --time=48:00:00
#SBATCH --mem=10G
#SBATCH --mail-type=END
#SBATCH --mail-type=FAIL
#SBATCH --mail-user=my@mail.com
#SBATCH --ntasks=<SOME NUMBER>

cd my_dir

parallel -P SLURM_NTASKS srun -n 1 -c 1 --exclusive Rscript /hpc/someRscript.R ::: 1 2 ::: 1 2 3 4 ::: 1 2 3 ::: 1 2 3 4 ::: 5 10 15 20 30 40 50 75 100 200 300 400 500 750 1000 1250 1500 1750 2000

echo done

将其转换为作业数组并非易事。一小步就是以最里面的循环为例(最大的)并在该参数上运行数组

#!/usr/bin/bash

#SBATCH --time=48:00:00
#SBATCH --mem=10G
#SBATCH --mail-type=END
#SBATCH --mail-type=FAIL
#SBATCH --mail-user=my@mail.com
#SBATCH --ntasks=<SOME NUMBER>
#SBATCH --array=0-18

cd my_dir

INIT=(5 10 15 20 30 40 50 75 100 200 300 400 500 750 1000 1250 1500 1750 2000)

parallel -P SLURM_NTASKS srun -n 1 -c 1 --exclusive Rscript /hpc/someRscript.R {} ${INIT[$SLURM_ARRAY_TASK_ID]} ::: 1 2 ::: 1 2 3 4 ::: 1 2 3 ::: 1 2 3 4 

echo done

只要在 Bash 数组中创建所有组合并使用 $SLURM_ARRAY_TASK_ID 对它们进行索引,就可以对所有组合运行该数组。

【讨论】:

    猜你喜欢
    • 2021-05-16
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-27
    相关资源
    最近更新 更多