std::execution::sequenced_policy, std::execution::parallel_policy, std::execution::parallel_unsequenced_policy
提供: cppreference.com
ヘッダ <execution> で定義
|
||
class sequenced_policy { /* unspecified */ }; |
(1) | (C++17以上) |
class parallel_policy { /* unspecified */ }; |
(2) | (C++17以上) |
class parallel_unsequenced_policy { /* unspecified */ }; |
(3) | (C++17以上) |
1) 並列アルゴリズムのオーバーロードの曖昧性を解決し、並列アルゴリズムの実行が並列化されてはならないことを要求するために、一意な型として使用される実行ポリシー型です。 このポリシー (通常 std::execution::seq として指定されます) を用いて呼び出された並列アルゴリズムにおける要素アクセス関数の呼び出しは、呼び出し元スレッド内で不定の順序に配列されます。
2) 並列アルゴリズムのオーバーロードの曖昧性を解決し、並列アルゴリズムの実行が並列化されても構わないことを示すために、一意な型として使用される実行ポリシー型です。 このポリシー (通常 std::execution::par として指定されます) を用いて呼び出された並列アルゴリズムにおける要素アクセス関数の呼び出しは、呼び出し元スレッド、または並列アルゴリズムの実行をサポートするためにライブラリによって暗黙に作成されたスレッドのいずれかで実行することが許されます。 同じスレッド内で実行されるあらゆるそのような呼び出しは、お互い不定の順序に配列されます。
3) 並列アルゴリズムのオーバーロードの曖昧性を解決し、並列アルゴリズムの実行が並列化されたり、ベクトル化されたり、あるいは (ペアレントスティーリングスケジューラなどによって) スレッド間で移送されたりしても構わないことを示すために、一意な型として使用される実行ポリシー型です。 このポリシーを用いて呼び出された並列アルゴリズムにおける要素アクセス関数の呼び出しは、未規定のスレッドで、各スレッド内の他のアクセスに対しても配列されず、順序付けされない方法で実行されることが許されます。
これら3種類の実行ポリシーのいずれかを用いた並列アルゴリズムの実行中に要素アクセス関数の実行がキャッチされない例外によって終了した場合は、 std::terminate が呼ばれます。 処理系は例外を異なる方法で処理する追加の実行ポリシーを定義しても構いません。
[編集] ノート
並列実行ポリシーを使用するときにデッドロックを回避するのはプログラマの責任です。
int a[] = {0,1}; std::vector<int> v; std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int i) { v.push_back(i*2+1); // Error: data race });
std::atomic<int> x{0}; int a[] = {1,2}; std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { x.fetch_add(1, std::memory_order_relaxed); while (x.load(std::memory_order_relaxed) == 1) { } // Error: assumes execution order });
int x = 0; std::mutex m; int a[] = {1,2}; std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { std::lock_guard<std::mutex> guard(m); ++x; // correct });
配列されない実行ポリシーは、関数呼び出しがお互いに対して配列されない、つまりインターリーブできることを意味する、唯一のケースです。 C++ の他のあらゆる状況では、それらは不定に配列されます (インターリーブできません)。 そのため、このポリシーを使用するときは、メモリの確保や解放、ミューテックスの取得、ロックフリーでない std::atomic の特殊化、および他のあらゆるベクトル化セーフでない操作を行うことは許されません (ベクトル化セーフでない関数とは、別の関数に対して同期する関数です。 例えば std::mutex::unlock は次の std::mutex::lock に対して同期します)。
int x = 0; std::mutex m; int a[] = {1,2}; std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard<std::mutex> guard(m); // Error: lock_guard constructor calls m.lock() ++x; });
[編集] 関連項目
(C++17)(C++17)(C++17) |
グローバルな実行ポリシーオブジェクト (定数) |