我有一个大型并行(使用MPI)模拟应用程序,它可以生成大量数据。为了评估这些数据,我使用了一个python脚本。
我现在需要做的是多次运行此应用程序(> 1000)并从结果数据中计算统计属性。
到目前为止,我的方法是让一个python脚本并行运行(使用mpi4py,使用48个节点),使用subprocess.check_call
调用模拟代码。
我需要这个调用来串行运行我的mpi模拟应用程序。
在这种情况下,我不需要模拟并行运行。
然后python脚本可以并行分析数据,完成后将启动一个新的模拟运行,直到累积大量的运行。
目标是
Stub MWE:
multi_call_master.py
:from mpi4py import MPI
import subprocess
print "Master hello"
call_string = 'python multi_call_slave.py'
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
print "rank %d of size %d in master calling: %s" % (rank, size, call_string)
std_outfile = "./sm_test.out"
nr_samples = 1
for samples in range(0, nr_samples):
with open(std_outfile, 'w') as out:
subprocess.check_call(call_string, shell=True, stdout=out)
# analyze_data()
# communicate_results()
multi_call_slave.py
(这将是C模拟代码):from mpi4py import MPI
print "Slave hello"
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
print "rank %d of size %d in slave" % (rank, size)
这不起作用。 stdout
中产生的结果:
Master hello
rank 1 of size 2 in master calling: python multi_call_slave_so.py
Master hello
rank 0 of size 2 in master calling: python multi_call_slave_so.py
[cli_0]: write_line error; fd=7 buf=:cmd=finalize
:
system msg for write_line failure : Broken pipe
Fatal error in MPI_Finalize: Other MPI error, error stack:
MPI_Finalize(311).....: MPI_Finalize failed
MPI_Finalize(229).....:
MPID_Finalize(150)....:
MPIDI_PG_Finalize(126): PMI_Finalize failed, error -1
[cli_1]: write_line error; fd=8 buf=:cmd=finalize
:
system msg for write_line failure : Broken pipe
Fatal error in MPI_Finalize: Other MPI error, error stack:
MPI_Finalize(311).....: MPI_Finalize failed
MPI_Finalize(229).....:
MPID_Finalize(150)....:
MPIDI_PG_Finalize(126): PMI_Finalize failed, error -1
sm_test.out
中的结果输出:
Slave hello
rank 0 of size 2 in slave
原因是,子进程假定作为并行应用程序运行,而我打算将其作为串行应用程序运行。 作为一个非常“hacky”的解决方法,我做了以下几点:
如果我现在使用intel mpi开始我的并行python脚本,底层模拟将不会意识到周围的并行环境,因为它使用的是不同的库。
这种方法运行良好一段时间,但不幸的是,由于各种原因,它不是很便携,很难在不同的集群上维护。
我可以
srun
将子进程调用循环放入shell脚本
MPI_Comm_spawn
技术
mpirun -n 1
或srun
进行子进程调用无效有没有优雅,官方的方式这样做?我真的没有想法,感谢任何意见!
答案 0 :(得分:6)
不,既没有优雅也没有官方的方式来做到这一点。从MPI应用程序中执行其他程序的唯一官方支持的方法是使用MPI_Comm_spawn
。通过subprocess
提供的简单操作系统机制产生子MPI进程是危险,在某些情况下甚至可能产生灾难性后果。
虽然MPI_Comm_spawn
没有提供查找子进程何时退出的机制,但您可以使用intercomm barrier来模拟它。您仍然会遇到问题,因为MPI_Comm_spawn
调用不允许任意重定向标准I / O,而是将其重定向到mpiexec
/ mpirun
。
您可以做的是编写一个包装脚本,删除MPI库可能使用的所有可能路径,以便传递会话信息。对于Open MPI,它可以是以OMPI_
开头的任何环境变量。对于英特尔MPI,它将是以I_
开头的变量。等等。有些库可能会使用文件或共享内存块或其他一些操作系统机制,您也必须处理这些内容。一旦消除了任何可能的通信MPI会话信息的机制,您就可以简单地启动可执行文件,它应该形成一个单独的MPI作业(就像运行mpiexec -n 1
一样)。