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
函数)。
我一直在研究 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
函数)。