我正在尝试使用一个简单的 bash 脚本按顺序运行一批 MPI 作业。此脚本在运行串行代码时运行良好(我使用的是 Fortran 90),但由于某种原因,当我尝试执行 MPI 代码时,bash 会脱离循环。
我已经找到了解决这个问题的方法。我只是用Perl写了本质上完全相同的脚本,它工作起来非常棒。我真的很想理解这里的问题,因为我更喜欢bash的简单性,它完全符合我自己在几乎所有其他情况下的脚本需求。
我尝试将 MPI 代码作为后台进程运行并使用具有相同结果的等待。如果我在不使用 wait 的情况下在后台运行作业,bash 不会脱离循环,但它会堆叠作业直到最终崩溃。无论如何,目标是为每个参数集按顺序运行可执行文件,我只是想指出在这种情况下循环不会中断。
Bash 脚本,interp.sh:用法 --
#!/bin/bash
PROG=$1
IFILE=$2
kount=0 # Counter variable for looping through input file
sys=0 # Counter variable to store how many times model has been run
while IFS="\n" read -r line
do
kount=$(( $kount + 1 ))
if [ $(( kount % 2 )) -eq 1 ] # if kount is even, then expect headers
then
unset name defs
sys=$(( $sys + 1 ))
name=( $line ) # parse headers
defs=${#name[*]}
k=$(( $defs - 1 ))
else # if count is odd, then expect numbers
unset vals
vals=( $line ) # parse parameters
for i in $( seq 0 $k )
do
# Define variables using header names and set their values
printf -v "${name[i]}" "${vals[i]}"
done
# Print input variable values
echo $a $b $c $d $e $nPROC
# Run executable
mpiexec -np $nPROC --oversubscribe --hostfile my_hostfile $PROG
fi
done < $IFILE
输入文件,Input.dat:
a b c d e nPROC
1 2 3 4 5 2
nPROC
3
nPROC
4
nPROC
5
nPROC
6
nPROC
7
nPROC
8
示例MPI f90代码,main.f90:
program main
use mpi
implicit none
integer :: i, ierr, myID, nPROC
integer, parameter :: foolen = 100000
double precision, dimension(0:foolen) :: foo
call MPI_INIT(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nPROC, ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, myID, ierr)
if ( myID .eq. 0 ) then
do i=0,foolen
foo(i) = i
end do
else
do i=0,foolen
foo(i) = i
end do
end if
call MPI_FINALIZE(ierr)
end program
示例makefile:
COMP=mpif90
EXT=f90
CFLAGs=-Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=all \
-fbacktrace
MPIflags=--oversubscribe --hostfile my_hostfile
PROG=main.x
INPUT=input.dat
OUTPUT=output
OBJS=main.o
$(PROG): $(OBJS)
$(COMP) $(CFLAGS) -o $(PROG) $(OBJS) $(LFLAGS)
main.o: main.f90
$(COMP) -c $(CFLAGs) main.f90
%.o: %.f90
$(COMP) -c $(CFLAGs) $<
run:
make && make clean
./interp.sh $(PROG) $(INPUT)
clean:
rm -f *.o DONE watch
my_hostfile
localhost slots=4
请注意,如果mpiexec行被注释掉,则脚本按预期运行。输出如下所示:
1 2 3 4 5 2
1 2 3 4 5 3
1 2 3 4 5 4
1 2 3 4 5 5
1 2 3 4 5 6
1 2 3 4 5 7
1 2 3 4 5 8
这些是应该在每个循环中传递给 MPI 代码的参数值。但是,在脚本中调用 mpiexec 时,仅读取和传递第一组参数。
我很抱歉,如果这一切有点过分,我只是想提供测试所需的一切。任何帮助解决bash中的问题或解释为什么会发生这种情况将不胜感激!
< code>mpiexec正在消耗< code>stdin,从而读取循环中所有剩余的行。所以在第一次循环后< code>stdin为空,循环中断。
这是一个问题,不仅会出现在从Whatson调用mpiexec
的循环中,还会出现在默认情况下使用stdin
的其他命令的循环中,例如ssh
。
一般的解决方案是使用
因此,这种情况下的解决方案是在调用mpiexec的行尾添加重定向:
mpiexec -np $nPROC --oversubscribe --hostfile my_hostfile $PROG < /dev/null
在与标准I/O相关的< code>mpiexec的情况下,有一些需要注意的问题,在此详述:https://www.open-mpi.org/doc/v3.0/man1/mpiexec.1.php#toc14