wait -n 的替代方案(因为服务器有旧版本的 bash)

wait -n 的替代方案(因为服务器有旧版本的 bash)

我想解决以下有关提交已并行到特定节点的作业的问题。


让我首先解释一下我的问题的结构

我有两个非常简单的 Matlab 脚本

1) 主.m

clear
rng default
P=2;
grid=randn(4,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;

  • 然后,运行调频4次,允许并行执行每次2个任务

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


这是我实施上述步骤的方法

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

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

#!/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

J=4 #number tasks

N=2 #number tasks executed in parallel

export SGE_TASK_ID


SGE_TASK_ID=1
n=0
while [ "$SGE_TASK_ID" -le "$J" ]; do
    if [ "$n" -eq "$N" ]; then
        wait -n  # as soon as one task is done, refill it with another
        n=$(( n - 1 ))
    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

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


问题:我收到以下错误

td.sh: line 26: wait: -n: invalid option
wait: usage: wait [id]

正如下面的评论中所注意到的,问题在于 @A 上的 bash 版本很旧(-n 选项已添加到 4.3 中的 wait 内置函数中)并且系统管理员无法更新它。最新的版本可能是 bash 4.1。

因此,您能建议一种替换方法wait -n吗?

答案1

您编写的脚本可以更好地使用 gnu parallel 来完成,或者使用 -j 选项来完成。或者,您可以用 python(或其他语言)重新编写它。

看着

  • parallel:一个在 bash 中使用的工具(三个中最容易学习的,只做一件事)。
  • make:更高级一点,它有自己的语言。它用于创建文件。例如,为了让A.b你需要A.a,并且g.f,当你有这些时,做z;y;z。您还可以添加有关如何制作A.a和 的规则g.f。它将计算出什么取决于什么,并以正确的顺序构建事物。如果可以的话,它会并行地做事情(如果要求的话)。
  • python:一种编程语言,它可以做你的脚本想要做的事情,它可以做matlab所做的事情。

您还必须考虑哪些是/可以安装的。这样做可以找出:

type parallel
type make
type python

注意:type这不是给您打字的指令。这是您输入的命令。它告诉您每个命令的类型(它在哪里)。

答案2

在 while 循环中根本不使用 wait 怎么样?

while [ "$SGE_TASK_ID" -le "$J" ]; do

    # grep count of matlab processes out of list of user processes
    n = $(ps ux | grep -c "matlab")

    ##  if [ "$n" -le "$N" ]; then
    if [ "$n" -eq "$N" ]; then
        # sleep 1 sec if already max processes started
        sleep 1
        ##  wait -n  # as soon as one task is done, refill it with another
        ##  n=$(( n - 1 ))
    else
        # start another process
        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 ))

    fi
    ##  n=$(( n + 1 ))
done

当然,grep 的字符串可能会有所不同,具体取决于您运行的内容(例如,给出f.m一些更特殊的名称,然后使用 grep 来表示它。)

答案3

您的 shell 脚本看起来很可疑,就像是为分布式资源管理器(可能是 gridengine)编写的,它支持开箱即用地并行运行多个事物,而不需要 shell 脚本。为什么不使用这些功能呢?

qsub -t 1-4 ./script.sh

然后删除所有修改 SGE_TASK_ID 值的行——gridengine 将为您设置它。

(您也可以在脚本中设置选项,#$-t 1-4如果您愿意的话,可以使用一行,当然......)

答案4

您可以自己安装:

对于大多数软件来说,安装过程中唯一需要 root 权限的部分是将文件复制到标准位置。 (对于设备驱动程序、内核、虚拟机等而言并非如此)

我建议将 Bash 安装到您的主目录 ( ~/bin) 并让您的脚本使用它。

相关内容