【发布时间】:2021-11-19 19:11:37
【问题描述】:
我有一个大型(相当复杂...)C++/MPI 代码库。这段代码的一部分已经发展成一个不抛出异常区域,因为当一个进程抛出一个未捕获的异常时,MPI 应用程序将死锁——在未捕获异常的情况下,我只希望整个应用程序(包括所有 MPI 进程终止)。据我了解,MPI_ABORT(MPI_COMM_WORLD) 调用将终止所有 MPI 进程 - 我一直在玩弄这样的自定义异常:
class my_exception {
public:
explicit my_exception(const std::string& m) :
msg(m)
{}
~my_exception() {
if (!this->handled)
Mpi_abort();
}
void handle() {
this->handled = true;
}
private:
std::string msg;
bool handled{false};
}
这样做的目的是确保为未捕获异常调用MPI_ABORT()。在确实捕获到异常的情况下
catch 块必须改变异常对象的状态以确保安全销毁 - 即“OK”。应用程序陷入火海也是“可以的”——目前的僵局更糟。
我还没有尝试过 - 但如果有人能提前判断它是否可行,我会很感兴趣。避免僵局的替代方法也非常受欢迎。
【问题讨论】:
-
你说
catch块是必需的。那么在这样的 catch 块中显式调用MPI_Abort不是更好吗?我相信它至少会更容易理解。此外,此解决方案将如何处理其他类型的异常(例如std::bad_alloc等)? -
catch块和exception_instance.handle()调用是必需的,以避免调用MPI_Abort()- 如果异常未处理,则应调用MPI_Abort()并且整个应用程序将陷入困境。 -
它可能无法与
std::bad_alloc等其他异常一起正常工作 - 但这也是现在的情况 - 即当前抛出例如std:bad_alloc()将在应用程序的一个进程部分的后续 MPI 调用中导致死锁。 -
将
main的功能通过try块“包装”并在其catch块中调用MPI_Abort不是更好吗?它将涵盖所有异常,无论其类型如何。我们也在 HPC 应用程序中使用这种方法,因为死锁会浪费大量超级计算资源,而这些资源通常非常有限。 -
wrap main 是个好主意!如果你做出这个答案,我会接受!