繁体   English   中英

mpi4py 在使用 spawn 后进入死锁

[英]mpi4py enters deadlock after using spawn

我有以下代码安排:

父母.py

from mpi4py import MPI

... some code ...

for i in range(10):

    ... some code ...

    child_comm = MPI.COMM_SELF.Spawn(sys.executable, args=["runscript_airfoil.py"], maxprocs=9)
    child_comm.Barrier()
    child_comm.Disconnect()

    ... some code ...

孩子.py

from mpi4py import MPI

... some code ...

comm = MPI.COMM_WORLD
comm.Barrier()

这里的主要目标是一次又一次地使用多个处理器运行child.py 我在这里使用了Barrier()方法,因为我希望程序等到child.py被执行。

但是,程序在第一次迭代后就停止了。 我认为该计划正在陷入僵局。 此外,应该释放child.py使用的所有处理器,以便我可以在下一个循环中使用它们。

我是 MPI 和 mpi4py 的新手,所以我不知道在哪里使用什么功能。 任何帮助实现这一点都将非常有用。

编辑 1

根据评论,我将child.py文件的内容修改为以下内容:

from mpi4py import MPI

... some code ...

comm = MPI.COMM_WORLD
parent_comm = comm.Get_parent()
comm.Barrier()
parent_comm.Disconnect()

程序在第一次迭代后仍然卡住。

编辑 2

根据评论,我进一步修改child.py文件的内容如下:

from mpi4py import MPI

... some code ...

comm = MPI.COMM_WORLD
parent_comm = comm.Get_parent()
parent_comm.Barrier()
parent_comm.Disconnect()

该程序没有进入死锁,但是当它尝试在第二次迭代中生成时,它会出现以下错误:系统中没有足够的可用插槽来满足应用程序请求的 9 个插槽。 我的笔记本电脑总共有 10 个处理器,1 个在运行 parent.py 和 rest 9 个在第一次迭代中运行 child.py。 当 parent.py 尝试使用 9 个处理器第二次生成 child.py 时,它没有使用之前使用的 9 个处理器,而是试图找到 9 个新处理器(不可用)。 我认为之前的 spawn 并没有完全退出。 为了测试这个理论,我运行了原始的parent.pychild.py (来自第二次编辑),其中 maxprocs 为 3 并循环了三次。 这工作得很好。

使用什么命令来完全释放处理器?

编辑 3

我在编辑 2 末尾的评估是正确的。 我发现当我将 maxprocs 保持为 4 或更少时,无论循环次数如何,它都可以正常工作。 当我将 maxprocs 保持为 5 或更多时,它才会开始给出“插槽不足”错误。 我不确定这里的问题是什么。

跟随 MWE 工作而不会陷入僵局(感谢@Giles 在评论部分的讨论:):

父母.py

from mpi4py import MPI

comm = MPI.COMM_WORLD

for i in range(10):

    print("Start {}".format(i))

    child_comm = MPI.COMM_WORLD.Spawn(sys.executable, "child.py", maxprocs=9)
    child_comm.Disconnect()

    print("End {}".format(i))

孩子.py

import time
from mpi4py import MPI

comm = MPI.COMM_WORLD
time.sleep(comm.rank)
print(comm.rank)

parent_comm = comm.Get_parent()
parent_comm.Disconnect()

这在mpi4py 教程中也有描述(之前应该已经看过)。

在这一点之后,我遇到了另一个错误。 当我将 parent.py 作为python parent.py运行时,我曾经得到以下 output:

Start 0
0
3
4
7
1
6
2
8
5
End 0
Start 1
--------------------------------------------------------------------------
There are not enough slots available in the system to satisfy the 9
slots that were requested by the application:

  /home/pavan/miniconda3/envs/codelab/bin/python

Either request fewer slots for your application, or make more slots
available for use.

A "slot" is the Open MPI term for an allocatable unit where we can
launch a process.  The number of slots available are defined by the
environment in which Open MPI processes are run:

  1. Hostfile, via "slots=N" clauses (N defaults to number of
     processor cores if not provided)
  2. The --host command line parameter, via a ":N" suffix on the
     hostname (N defaults to 1 if not provided)
  3. Resource manager (e.g., SLURM, PBS/Torque, LSF, etc.)
  4. If none of a hostfile, the --host command line parameter, or an
     RM is present, Open MPI defaults to the number of processor cores

In all the above cases, if you want Open MPI to default to the number
of hardware threads instead of the number of processor cores, use the
--use-hwthread-cpus option.

Alternatively, you can use the --oversubscribe option to ignore the
number of available slots when deciding the number of processes to
launch.
--------------------------------------------------------------------------
Traceback (most recent call last):
  File "parent.py", line 30, in <module>
    child_comm = MPI.COMM_WORLD.Spawn(sys.executable, "child.py", maxprocs=9)
  File "mpi4py/MPI/Comm.pyx", line 1931, in mpi4py.MPI.Intracomm.Spawn
mpi4py.MPI.Exception: MPI_ERR_SPAWN: could not spawn processes

我的笔记本电脑有 10 个内核(使用 lscpu 验证,我使用 mpirun 命令运行了 10 个处理器的脚本)。 我将脚本运行为mpirun -n 1 python parent.py但我仍然遇到相同的错误。

经过一番折腾,我发现在 parent.py 中的 Disconnect 方法后添加一个小的停顿有效: parent.py

import time
from mpi4py import MPI

comm = MPI.COMM_WORLD

for i in range(10):

    print("Start {}".format(i))

    child_comm = MPI.COMM_WORLD.Spawn(sys.executable, "child.py", maxprocs=9)
    child_comm.Disconnect()
    time.sleep(0.25)

    print("End {}".format(i))

Output :

Start 0
7
6
8
4
5
1
0
3
2
End 0
Start 1
7
8
1
6
5
3
2
4
0
End 1

我不确定为什么会这样,但我建议在 Disconnect 方法结束之前,for 循环会尝试生成下一组进程。 因此,添加一个小的停顿可以让 Disconnect 方法有一些时间完成。 我不确定这在使用 MPI(或 mpi4py)时是否常见,但如果有一种优雅的方法来克服这个问题,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM