11

OpenMP は、例外によって openmp ブロックを終了するコードを禁止します。したがって、メインスレッドで例外を再スローし、後で処理する目的で、openmp ブロックから例外を取得する良い方法を探しています。これまでのところ、私が思いついた最高のものは次のとおりです。

class ThreadException {
    std::exception_ptr Ptr;
    std::mutex         Lock;
public:
    ThreadException(): Ptr(nullptr) {}
    ~ThreadException(){ this->Rethrow(); }  
    void Rethrow(){
        if(this->Ptr) std::rethrow_exception(this->Ptr);
    }
    void CaptureException() { 
        std::unique_lock<std::mutex> guard(this->Lock);
        this->Ptr = std::current_exception(); 
    }   
};
//...
ThreadException except;
#pragma omp parallel
{
    try {
      //some possibly throwing code
    } 
    catch(...) { except.CaptureException(); }
}

これはうまく機能し、オブジェクトが破棄されるとすぐに並列セクションから可能な例外を再スローしますが、この構成は、各セクションを囲んで手動で例外をキャプチャする必要がThreadExceptionあるため、使用するにはまだ少し扱いに​​くいです。try {}catch(...){}

だから私の質問は、これを行うためのよりエレガントな(冗長でない)方法を知っている人はいますか(もしそうなら、それはどのように見えますか)?

4

1 に答える 1

15

さらにいくつかの C++11 ツールを使用して、構文を少しクリーンアップできます。この可変引数メンバー関数をThreadExceptionクラスに追加します。

class ThreadException {

    // ...

    template <typename Function, typename... Parameters>
    void Run(Function f, Parameters... params)
    {
        try 
        {
            f(params...);
        }
        catch (...)
        {
            CaptureException();
        }
    }
 };

次に、OpenMP コンストラクト内で呼び出すときに、次のようにラムダ関数を使用します。

ThreadException e;

#pragma omp parallel for
for (int i = 0; i < n; i++)
{
    e.Run([=]{
        // code that might throw
        // ...
    });
}
e.Rethrow()
于 2012-12-20T18:45:08.053 に答える