yohhoyの日記

技術的メモをしていきたい日記

OpenMPとC++例外の危険な関係

OpenMP並列化領域内からC++例外を送出する場合、例外を送出したスレッドと同一スレッド上で例外catchを行う必要がある。すなわちOpenMPスレッドをまたぐC++例外伝搬は行われず、またOpenMP並列化領域の中から外へC++例外が送出されてはならない。このルールに反する場合、実行時クラッシュなどを引き起こす可能性がある。

#pragma omp parallel for
for (int i = 0; i < 100; i++) {
  //...
  throw i;  // NG: parallel領域を超えてC++例外が送出される
}
#include <memory>
#include <new>

#pragma omp parallel thread_num(2)
{
  try {
    //...
    auto = std::make_shared<T>(/*...*/);  // ::new
    //...
  } catch (const std::bad_alloc& e) {
    // OK: 同一スレッド内でcatchすれば問題ない
  }
}

OpenMP C/C++ API v2.0仕様*1 1.2 Definition of Terms, 2.3 parallel Constructsより該当箇所を引用。

structured block
A structured block is a statement (single or compound) that has a single entry and a single exit. No statement is a structured block if there is a jump into or out of that statement (including a call to longjmp(3C) or the use of throw, but a call to exit is permitted). (snip)
dynamic extent

Restrictions to the parallel directive are as follows:

  • (snip)
  • A throw executed inside a parallel region must cause execution to resume within the dynamic extent of the same structured block, and it must be caught by the same thread that threw the exception.
  • (snip)

関連URL