我经常使用类似下面简化的2个脚本的东西,用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[@]}
Running提供所需的输出:
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
有没有办法用mpirun命令内联写入worker_script.sh的内容?除了单独的文件之外,是否存在由父进行shell扩展的方法?
答案 0 :(得分:2)
任何看起来像
的东西#!/bin/bash
stuff
here
(除了带有此处文档的脚本)可以等效地在单个逻辑行上表示为
bash -c 'stuff; here'
甚至更可读
bash -c 'stuff
here'
(在这种情况下,您甚至可以嵌入此处的文档。)
如果您的脚本包含单引号,那么显然必须以某种方式解决。
将脚本放在单引号内可以保护它免受通配符扩展,变量替换等的影响。
只是因为你的意思并不代表你应该这样做。
答案 1 :(得分:2)
感谢您的回答,他们引发了有趣的研究。到目前为止,我个人首选的解决方案是对triee的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的语法突出显示一起使用。
答案 2 :(得分:0)
唔不......通常不会。 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
所需的信息。