gpt4 book ai didi

python - 串行调用 mpi 二进制文件作为 mpi 应用程序的子进程

转载 作者:太空狗 更新时间:2023-10-29 23:59:17 24 4
gpt4 key购买 nike

我有一个生成大量数据的大型并行(使用 MPI)模拟应用程序。为了评估这些数据,我使用了 Python 脚本。

我现在需要做的是多次运行此应用程序 (>1000) 并根据结果数据计算统计属性。

到目前为止,我的方法是让 python 脚本并行运行(使用 mpi4py,使用即 48 个节点)使用 subprocess.check_call 调用模拟代码。我需要这个调用来串行运行我的 mpi 模拟应用程序。在这种情况下,我不需要模拟也并行运行。然后python脚本可以并行分析数据,完成后将启动新的模拟运行,直到积累大量运行。

目标是

  • 不保存 2000 次运行的整个数据集
  • 将中间数据保存在内存中

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”的解决方法,我做了以下事情:

  • 使用特定的 mpi 发行版编译所有需要的 mpi 感知库,即 intel mpi
  • 使用不同的 mpi 库编译模拟代码,即 openmpi

如果我现在使用 intel mpi 启动我的并行 python 脚本,底层模拟将不知道周围的并行环境,因为它使用的是不同的库。

这在一段时间内运行良好,但不幸的是,由于各种原因,它不是很便携并且难以在不同的集群上维护。

我可以

  • 使用 srun 将子进程调用循环放入 shell 脚本中
    • 将要求在 HD 上缓冲结果
  • 在 python 中使用某种MPI_Comm_spawn技术
    • 不应该那样使用
    • 很难知道子进程是否完成
    • 必要时适当更改 C 代码
  • 以某种方式欺骗子进程不转发 MPI 信息
    • 试图操纵环境变量无济于事
    • 也不意味着那样使用
    • 对子进程调用使用mpirun -n 1srun 没有帮助

有什么优雅的官方方法可以做到这一点吗?我真的没有想法,感谢任何意见!

最佳答案

不,既没有优雅的也没有官方的方法来做到这一点。从 MPI 应用程序中执行其他程序的唯一官方支持的方法是使用 MPI_Comm_spawn。通过简单的操作系统机制(如 subprocess 提供的机制)生成子 MPI 进程是危险的,在某些情况下甚至可能产生灾难性后果。

虽然 MPI_Comm_spawn 没有提供一种机制来查明子进程何时退出,但您可以使用内部通信屏障来模拟它。您仍然会遇到问题,因为 MPI_Comm_spawn 调用不允许任意重定向标准 I/O,而是重定向到 mpiexec/mpirun.

您可以做的是编写一个包装器脚本,删除 MPI 库可能使用的所有可能路径,以便传递 session 信息。对于 Open MPI,它可以是任何以 OMPI_ 开头的环境变量。对于英特尔 MPI,这将是以 I_ 开头的变量。等等。一些库可能使用文件或共享内存块或一些其他操作系统机制,您也必须注意这些。一旦消除了任何可能的 MPI session 信息通信机制,您就可以简单地启动可执行文件,它应该形成一个单独的 MPI 作业(也就是说,表现得就像使用 mpiexec -n 1 运行一样)。

关于python - 串行调用 mpi 二进制文件作为 mpi 应用程序的子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21090085/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com