将嵌套的bash脚本减少到单个文件/mpirun命令



我经常使用下面的简化脚本来通过PBS/MPI在集群中分发令人尴尬的并行工作。我想知道,如果命令可以合并到一个文件的清晰度和减少混乱。我更感兴趣的是了解bash/mpirun的局限性,而不是寻找解决原始问题(如PBS数组)的替代方法。

PBS脚本:

#PBS -l nodes=2:ppn=2
#PBS -q debug
#PBS -V
mpirun -n $PBS_NP $PBS_O_WORKDIR/worker_script.sh

worker_script.sh

#!/bin/bash
NDATA=25
DATA_ARRAY=()
for ((DATA=${OMPI_COMM_WORLD_RANK};DATA<${NDATA};DATA=${DATA}+${PBS_NP}))
do
    DATA_ARRAY+=(${DATA})
done
echo ${OMPI_COMM_WORLD_RANK} processing ${DATA_ARRAY[@]}

运行得到所需的输出:

0 processing 0 4 8 12 16 20 24
1 processing 1 5 9 13 17 21
3 processing 3 7 11 15 19 23
2 processing 2 6 10 14 18 22
----------------------------------------------------------------
Jobs exit status code is 0

是否有任何方法编写worker_script.sh内联与mpirun命令的内容?除了一个单独的文件之外,还有什么方法可以围绕父shell展开吗?

谢谢你的回答,它们带来了有趣的研究。到目前为止,我个人更喜欢的解决方案是扩展tripleee的bash -c技巧,将worker命令包装在导出函数中:

#!/bin/bash
#PBS -l nodes=2:ppn=2
#PBS -q debug
#PBS -V
# function
worker_function(){
NDATA=25
DATA_ARRAY=()
for ((DATA=${OMPI_COMM_WORLD_RANK};DATA<${NDATA};DATA=${DATA}+${PBS_NP}))
do
    DATA_ARRAY+=(${DATA})
done
echo ${OMPI_COMM_WORLD_RANK} processing ${DATA_ARRAY[@]}
}
# main
export -f worker_function
mpirun -n $PBS_NP bash -c 'worker_function'

这遵循典型的程序结构,并使用vim的语法高亮显示。

任何看起来像

#!/bin/bash
stuff
here

(保存为使用这里文档的脚本)可以等效地在单个逻辑行中表示为

bash -c 'stuff; here'

或者更容易读的

bash -c 'stuff
    here'

(在这种情况下,你甚至可以嵌入一个here文档。)

如果你的脚本包含单引号,那显然必须以某种方式解决。

将脚本放在单引号内可以防止通配符展开、变量替换等。

不…不是很经常。man mpirun"mpirun"是一个shell脚本,它试图对用户隐藏不同设备启动作业的差异。典型用法:

mpirun -np <number of processes> <program name and arguments>

mpirun接受一个程序名(或者在您的例子中是脚本名$PBS_O_WORKDIR/worker_script.sh)作为参数,所以通常它期望调用一个不同的文件。然而,关于批处理模式操作,mpirun有许多特定于机器的选项,在bash中,可能允许在PBS脚本中使用heredoc向mpirun提供所需的信息。

最新更新