当前位置: 首页 > 知识库问答 >
问题:

为什么我要打电话给MPI。析构函数中的Finalize()?

司空胤
2023-03-14

我目前正在尝试理解mpi4py。我设置了mpi4py.rc.initialize=Falsempi4py.rc.finalize=False,因为我不明白为什么我们想要自动初始化和终结。默认行为是在导入MPI时调用MPI. Init()。我认为这样做的原因是,对于每个等级,都运行了一个python解释器实例,每个实例都将运行整个脚本,但这只是猜测。最后,我喜欢把它说清楚。

现在这引入了一些问题。我有这个密码

import numpy as np
import mpi4py
mpi4py.rc.initialize = False  # do not initialize MPI automatically
mpi4py.rc.finalize = False # do not finalize MPI automatically

from mpi4py import MPI # import the 'MPI' module
import h5py

class DataGenerator:
    def __init__(self, filename, N, comm):
        self.comm = comm
        self.file = h5py.File(filename, 'w', driver="mpio", comm=comm)

        # Create datasets
        self.data_ds= self.file.create_dataset("indices", (N,1), dtype='i')

    def __del__(self):
        self.file.close()
        

if __name__=='__main__':
    MPI.Init()
    world = MPI.COMM_WORLD
    world_rank = MPI.COMM_WORLD.rank

    filename = "test.hdf5"
    N = 10
    data_gen = DataGenerator(filename, N, comm=world)

    MPI.Finalize()

导致

$ mpiexec -n 4 python test.py 
*** The MPI_Barrier() function was called after MPI_FINALIZE was invoked.
*** This is disallowed by the MPI standard.
*** Your MPI job will now abort. [eu-login-04:01559] Local abort after MPI_FINALIZE started completed successfully, but am not able to aggregate error messages, and not able to guarantee that all other processes were killed!
*** The MPI_Barrier() function was called after MPI_FINALIZE was invoked.
*** This is disallowed by the MPI standard.
*** Your MPI job will now abort. [eu-login-04:01560] Local abort after MPI_FINALIZE started completed successfully, but am not able to aggregate error messages, and not able to guarantee that all other processes were killed!
-------------------------------------------------------------------------- Primary job  terminated normally, but 1 process returned a non-zero exit code. Per user-direction, the job has been aborted.
--------------------------------------------------------------------------
*** The MPI_Barrier() function was called after MPI_FINALIZE was invoked.
*** This is disallowed by the MPI standard.
*** Your MPI job will now abort. [eu-login-04:01557] Local abort after MPI_FINALIZE started completed successfully, but am not able to aggregate error messages, and not able to guarantee that all other processes were killed!
-------------------------------------------------------------------------- mpiexec detected that one or more processes exited with non-zero status, thus causing the job to be terminated. The first process to do so was:

  Process name: [[15050,1],3]   Exit code:    1
--------------------------------------------------------------------------

我对这里发生的事情有点困惑。如果我移动MPI。Finalize()在析构函数的末尾,它可以正常工作。

并不是说我也使用h5py,它使用MPI进行并行化。我这里有一个并行文件IO。并不是说h5py需要使用MPI支持进行编译。您可以通过设置虚拟环境并运行pip安装--no binary=h5py h5py轻松实现这一点。

共有1个答案

暴绪
2023-03-14

按照您编写的方式,data\u-gen将一直存在,直到主函数返回。但是你调用MPI。在函数内完成。因此,析构函数在finalize之后运行。h5py。文件close方法似乎调用了MPI。内部通信屏障。禁止在完成后调用此命令。

如果您希望有显式的控制,请确保在调用MPI. Finize之前销毁所有对象。当然,如果某些对象只被垃圾收集器而不是引用计数器销毁,即使这样也可能不够。

要避免这种情况,请使用上下文管理器而不是析构函数。

class DataGenerator:
    def __init__(self, filename, N, comm):
        self.comm = comm
        self.file = h5py.File(filename, 'w', driver="mpio", comm=comm)

        # Create datasets
        self.data_ds= self.file.create_dataset("indices", (N,1), dtype='i')

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.file.close()


if __name__=='__main__':
    MPI.Init()
    world = MPI.COMM_WORLD
    world_rank = MPI.COMM_WORLD.rank

    filename = "test.hdf5"
    N = 10
    with DataGenerator(filename, N, comm=world) as data_gen:
        pass
    MPI.Finalize()
 类似资料:
  • 我目前正在尝试理解mpi4py。我设置了和,因为我不明白为什么我们想要自动初始化和终结。默认行为是在导入MPI时调用。我认为这样做的原因是,对于每个等级,都运行了一个python解释器实例,每个实例都将运行整个脚本,但这只是猜测。最后,我喜欢把它说清楚。 现在这引入了一些问题。我有这个密码 导致 我对这里发生的事情有点困惑。如果我移动到解构函数的末尾,它可以正常工作。 并不是说我也使用h5py,它

  • Vert.x Api 是很大程度上由事件驱动的。这意味着,当事情发生在你感兴趣的Vert.x,Vert.x 会通过回调方式向您发送events。 一些示例events: 计时器激活 socket收到数据 从磁盘读取数据 发生了异常 HTTP 服务器收到请求 通过向 Vert.x Api 提供处理程序来处理事件。例如要接收一个计时器事件每一秒你会做: vertx.setPeriodic(1000,

  • 问题内容: 我对此代码有疑问:https : //github.com/reactjs/redux/blob/master/examples/async/containers/App.js 特别: 我猜这是一个两部分的问题。 为什么我需要将句柄更改设置为类的实例,我不能只对handleChange使用静态函数并直接在类中调用它 ? 我不知道这是怎么回事: 谢谢 问题答案: 以相反的顺序回答… 返回

  • 我正在创建一个带有片段的应用程序,在其中一个片段中,我创建了一个非默认构造函数,并收到以下警告: 有人能告诉我为什么这不是个好主意吗? 你能否建议我如何做到这一点: 不使用非默认构造函数?

  • 调用对声明的东西返回围绕它构建的特殊注释。这很酷。我如何引用在类中定义的子例程?它总是隐藏的吗?我对提供子例程而不是类的模块很好奇(答案可能是“不要这样做”)。我主要是在玩以及我能走多远。 以下是输出: 这是我要问的最后一行输出。如何访问类中定义的子例程?

  • 通读Rust这本书,我遇到了一个有趣的话题——发散函数: Rust对“发散函数”有一些特殊的语法,这些函数不会返回: 发散函数可以用作任何类型: 发散函数的用例是什么?书上说 惊慌失措!()导致当前执行线程因给定消息而崩溃。因为这个函数会导致崩溃,它永远不会返回,所以它的类型是