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


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

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

3660
2017-09-21 17:16


起源



答案:


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 */

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

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


6
2017-09-27 20:23





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

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

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

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

MPI::COMM_WORLD.Set_errhandler ( MPI::ERRORS_THROW_EXCEPTIONS );

(如果您的库未配置为允许例外,这可能是个坏主意 - 根据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) ;
}

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

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


7
2017-09-27 18:21





并行执行期间异常是否有效取决于您的编译器和MPI库实现。如果你想要可移植的行为,我会避免在该上下文中抛出异常。

如果您想要更多有关错误的详细信息而不仅仅是数字返回码,您当然可以返回和/或传递错误字符串或其他对象(当然,在同一进程内或通过MPI)。


0
2017-09-27 16:42