【问题标题】:Call MPI_ABORT from exception destructor?从异常析构函数调用 MPI_ABORT?
【发布时间】: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 是个好主意!如果你做出这个答案,我会接受!

标签: c++ exception mpi


【解决方案1】:

@Daniel Langr 关于包装 main 的评论是一个更好的选择

【讨论】:

  • 抱歉,我有一段时间没有使用 Stack Overflow。自行回答自己的问题非常好。
猜你喜欢
  • 2013-11-07
  • 2015-12-22
  • 2012-04-15
  • 1970-01-01
  • 2022-01-16
  • 2014-07-06
  • 2015-08-26
相关资源
最近更新 更多