我是否允许在MPI并行化代码中抛出异常?

Han*_*ans 11 c++ parallel-processing exception

这些是我在为使用MPI(在C++中)并行运行的算法设计错误处理时遇到的一些常见问题:

  • 异常是否在并行执行的代码中工作?是否定义了行为?
  • 他们是如何工作的?对于不同的实现,这有何不同?
  • 这是好的做法 - 还是应该使用退货代码?

Joh*_*ter 7

在理想的世界中,您可以使用它们来做您所要求的事情."理想世界"是指您可以选择MPI实现并且能够自己管理它(而不是说服集群所有者为您重新配置它).异常的最小配置包括: - with-exceptions标志,可能还有一些.

我最常使用LAM,默认情况下禁用例外.我相信这也是其他实现的默认设置.

它们的工作方式与"vanilla"C++异常相同.他们确实在并行执行的代码中工作.

在启动代码中的某个时刻,您希望启用它们:

MPI::COMM_WORLD.Set_errhandler ( MPI::ERRORS_THROW_EXCEPTIONS );
Run Code Online (Sandbox Code Playgroud)

(如果您的库未配置为允许例外,这可能是一个坏主意 - 根据LAM,行为"未定义")

然后:

try { /* something that can fail */ } 
catch ( MPI::Exception e ) {

    cout << "Oops: " << e.Get_error_string() << e.Get_error_code();
    MPI::COMM_WORLD.Abort (-1) ;
}
Run Code Online (Sandbox Code Playgroud)

至于它的好坏,我实在无法说.我没有看到在强化MPI黑客编写的代码中广泛使用它们,但这可能是因为根据我的经验,代码通常比C++更多.

错误代码和异常之间的中间地带可能是错误处理程序,简而言之,您可以分配在发生特定错误(由代码指定)时将调用的函数.如果您无法让管理员加入启用例外,那么这可能是一个选项.


Jed*_*Jed 6

MPI代码中的异常与串行代码的作用相同,但是如果可能在通信器中的所有进程上都没有引发异常,或者您很容易导致死锁,则必须非常小心.

MPI_Barrier(comm);            /* Or any synchronous call */
if (!rank) throw Exception("early exit on rank=0");
MPI_Barrier(comm);            /* rank>0 deadlocks here because rank=0 exited early */
Run Code Online (Sandbox Code Playgroud)

所有错误处理方法都存在这个问题,很难从通信器中不一致的错误中恢复.在上面的例子中,你可以执行一个MPI_Allreduce所有等级选择相同的分支.

我的首选是调用错误处理程序并将它们传播到堆栈中,因为这会给我提供最有用/最详细的错误消息,并且很容易捕获断点(或错误处理程序可以将调试器附加到自身并将其发送给您工作站在xterm).