在 bash 文件中并行化 for 循环

在 bash 文件中并行化 for 循环

我想并行化下面的 bash 脚本中的 for 循环。


我有两个 Matlab 脚本

1) 主.m

clear
rng default
P=2;
grid=randn(2,3);
jobs=1;

2) 调频

sgetasknum_grid=grid(jobs*(str2double(getenv('SGE_TASK_ID'))-1)+1: str2double(getenv('SGE_TASK_ID'))*jobs,:); %jobsx3

result=sgetasknum_grid+1; 

filename = sprintf('result.%d.mat', ID);
save(filename, 'result')

exit

我想做的事:

  • 我想运行 main.m;

  • 然后,我想跑两次调频在平行下

  • 一切都应该在节点上执行A


这是我的版本没有并行化

1)我将 main.m 和 fm 保存到名为 My_folder 的文件夹中

2)我如下创建 bash 文件 td.sh 并将其保存到文件夹 My_folder 中

    #$ -S /bin/bash
    #$ -l h_vmem=5G
    #$ -l tmem=5G
    #$ -l h_rt=480:0:0
    #$ -cwd
    #$ -j y


    #$ -N try

    date
    hostname

    export SGE_TASK_ID

    for SGE_TASK_ID in {1..2}
do
    #Output the Task ID
    echo "Task ID is $SGE_TASK_ID"

  /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash -r "main; ID=$SGE_TASK_ID; f; exit"
done

3)我进入终端并输入ssh username@A,然后cd /.../My_folder,然后bash td.sh


为了并行化,本论坛很多答案都建议使用parallel。我猜 bash 文件看起来像下面这样

#$ -S /bin/bash
#$ -l h_vmem=5G
#$ -l tmem=5G
#$ -l h_rt=480:0:0
#$ -cwd
#$ -j y


#$ -N try

date
hostname

export SGE_TASK_ID

SGE_TASK_ID={1..2}

echo "$SGE_TASK_ID" | parallel -P 2 /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash -r "main; ID=$SGE_TASK_ID; f; exit"

但是,这是我在终端上收到的错误

A.local
td.sh: line 16: parallel: command not found

据我了解,可能是parallel机器中缺少“软件”。我可以安装它吗?如果可以,如何安装?或者应该由系统管理员安装?或者,您还有其他建议吗parallel


更新:尝试实现下面第二个答案的脚本

#!/bin/bash -l
#$ -S /bin/bash
#$ -l h_vmem=5G
#$ -l tmem=5G
#$ -l h_rt=480:0:0
#$ -cwd
#$ -j y


#$ -N try

date
hostname

export SGE_TASK_ID

SGE_TASK_ID={1..2}

echo -e SGE_TASK_ID | xargs -I {} -P 4 /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash  -r "main; ID={}; f; exit"

这是我收到的错误消息

Undefined function or variable 'SGE_TASK_ID'.

答案1

在循环中,在后台启动 Matlab 作业,然后等待它们在循环后完成:

for SGE_TASK_ID in 1 2; do
    printf 'Task ID is %d\n' "$SGE_TASK_ID"

    /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash \
        -r "main; ID=$SGE_TASK_ID; f; exit" &
done

wait

Matlab 作业将快速连续启动并同时运行。 afterwait循环确保脚本在所有后台作业完成之前不会退出。

对于J允许并行运行N作业的作业:

SGE_TASK_ID=1
n=0
while [ "$SGE_TASK_ID" -le "$J" ]; do
    if [ "$n" -eq "$N" ]; then
        wait  # waits for the N started jobs to finish
        n=0
    fi

    printf 'Task ID is %d\n' "$SGE_TASK_ID"

    /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash \
        -r "main; ID=$SGE_TASK_ID; f; exit" &

    SGE_TASK_ID=$(( SGE_TASK_ID + 1 ))
    n=$(( n + 1 ))
done

wait

另一种变化是等待单身的后台作业在循环的 - 语句内完成ifwait -n并且只需减n一而不是将其设置为零。

答案2

稍微干净一点的解决方案;

echo -e "1\n2" | xargs -I {} -P $(nproc) /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash  -r "main; ID={}; f; exit"

如果您有超过 2 个任务

相关内容