MPI.NET:运行 多个连续会话

MPI.NET: run multiple sequential sessions

我一直在研究 MPI.NET,但遇到了一个我似乎无法解决的问题。

在为 运行s MPI.NET 的代码创建测试时,我有两个单元测试 运行 按顺序由 MSTest 进行,每个单元测试都会创建一个通信器并进行处理。
执行此操作时,您最终会遇到通信器在第二次测试中既已初始化又已处置的情况(静态变量是此处的原因)。

我不打算从测试的角度来解决这个问题(运行以不同的方式进行测试不会解决问题)。 我只是向您展示那个案例,以便轻松地证明问题。

我希望有一个明智的方法来初始化 MPI.NET 两次,或者以某种方式回收它?

我确实联系了该项目的作者,他建议我 post 在这里,更熟悉 MPI 本身的人可能会提供帮助。

public static void RunMPIAction(Action<Intracommunicator> action)
{
    string[] args = null;
    using (var env = new Environment(ref args))
    {
        action(Communicator.world);
    }
}

MPI.Environment.RunMPIAction(comm =>
{
    this.Run(comm, logger, parameters);
}

MPI.Environment.RunMPIAction(comm => { int rank = comm.Rank; }, false);

MPI 不是为这样使用而设计的。创建新环境调用 MPI_Init_thread,其中指出:

This function must be called by one thread only. That thread will be known as the “Main Thread” and must be the same thread to call MPI_Finalize.

尝试从多个线程或一个线程多次调用它会失败。

处理 Environment 调用 MPI_Finalize,其中指出:

The MPI_Finalize function cleans up all state related to MPI. Once it is called, no other MPI functions may be called, including MPI_Init and MPI_Init_thread.

从中可以清楚地看出,每个进程只能有一个 Environment,并且一旦处置就无法重新创建它。

所以你必须重构你的代码来考虑到这一点。如果你有某种可重用的库——不要在那里初始化 MPI(只检查它是否已经初始化,如果没有则抛出)并且不要在那里完成它——只有那个库的 "top-level" 用户应该这样做。如果您没有引用已创建的 Environment 实例,但您需要完成环境,您可以这样做:

if (!MPI.Environment.Finalized)
    Unsafe.MPI_Finalize();

这样做没问题,因为 Environment 在语义上是一个单例,本来可以是静态的 class,但是由于方便 using 语句被设为非静态的(只有实例成员是 Dispose 函数)。