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

时间:2010-09-21 17:16:14

标签: c++ exception parallel-processing

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

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

3 个答案:

答案 0 :(得分:7)

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

我最常使用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 ++更多。

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

答案 1 :(得分:6)

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

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中的工作站。

答案 2 :(得分:0)

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

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