我有一个大规模并行(使用MPI)的模拟应用程序,它产生大量数据。为了评估这些数据,我使用Python脚本。
现在我需要做的是运行这个应用程序很多次(>1000),并从生成的数据中计算统计特性。
我的方法到目前为止是,让一个运行在并行中的Python脚本(使用mpi4py,例如使用48个节点)通过subprocess.check_call
调用模拟代码。
我需要这个调用以串行方式运行mpi模拟应用程序。
在这种情况下,我不需要模拟也以并行方式运行。Python脚本可以并行地分析数据,并在完成后启动新的模拟运行,直到积累了大量运行。
目标是
- 不保存来自2000次运行的整个数据集
- 将中间数据保存在内存中
示例代码:
文件 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”的解决方法,我做了以下几点:
- 使用特定的mpi发行版(例如intel mpi)编译所有需要mpi感知库
- 使用不同的mpi库(例如openmpi)编译模拟代码
这个方法一段时间内效果很好,但遗憾的是,在不同的集群上维护起来非常困难,也不太便携。
我可以:
- 将调用子进程的循环放入使用
srun
的shell脚本中- 需要在硬盘上缓存结果
- 在Python中使用某种
MPI_Comm_spawn
技术- 不适合此类用法
- 很难找出子进程是否已经完成
- 可能需要更改C代码
- 以某种方式欺骗子进程不转发MPI信息
- 尝试操作环境变量,但无济于事
- 这种方法也不适合此类用法
- 使用
mpirun -n 1
或srun
调用子进程无济于事
MPI_Comm_spawn
方法,但遇到了I/O问题,我将使用一个中间文件来进行管道bash脚本解决。对于完成检测,我将被迫修改C代码,因为中间bash脚本不起作用,因为它将涉及多个MPI_init
或多个MPI_Comm_spawn
...这一切都非常混乱,我不明白为什么这在MPI接口标准中没有得到很好的定义。 - Nils_Mfork()
在 Blue Gene 上不可用。因此,system()
也不受支持。 - Hristo IlievMPI_Comm_spawn
版本。 - Nils_M