C++1y(C++14)に向けた並列プログラミングモデルについてメモ。(PDF)N3711 Task Groups As a Lower Level C++ Library Solution To Fork-Join Parallelismにて、タスク並列処理の基本構成要素となるtask_groupコンセプトが提案されている。なお、同名クラスはIntel TBB(Threading Building Blocks)およびMicrosoft PPL(Parallel Pattern Library)でも提供される。
2014-01-20追記:N3711で言及されるtask_groupコンセプトは、(PDF)N3832 Task Regionにて task_region / task_run / task_wait へと分解されている。
task_groupコンセプトは “タスク並列(task parallel)”(→id:yohhoy:20120417)によるFork-Join並列パターン構築の基本機能を提供する。並列アルゴリズムを提案する(PDF)N3554 A Parallel Algorithms Libraryとは相補的な関係にあり、本N3711はでは最低限のクラス要件を定義するのみ*1。
例えば2関数を並行実行するparallel_invoke
関数は、task_group
クラスを利用して下記のように実装される(N3711より引用)。同様にparallel_for
等の代表的な並列アルゴリズムは、このtask_group
クラスを用いて実装可能。
template <typename Func1, typename Func2> void parallel_invoke(const Func1& f1, const Func2& f2) { task_group tg(/* ... */); tg.run(f1); tg.run_and_wait(f2); }
クラス要件
task_group
クラスは “例外リスト処理ハンドラ” 指定コンストラクタと3つのメンバ関数を提供する。コピー/ムーブ不可。
メンバ関数 | 説明 |
---|---|
template<EH> task_group(handler) |
例外リスト処理ハンドラ(関数オブジェクト)を指定してtask_group オブジェクトを構築する。 |
~task_group() | wait メンバ関数を呼び出し、必要ならば例外リスト処理ハンドラを呼び出す。 |
template<F, ...A> run(func, args) |
関数オブジェクトfunc に実引数群args を渡して呼び出すタスクを生成する。本メンバ関数呼び出しはブロッキングしない。 |
wait() | task_group オブジェクト上で生成された全タスクが完了するまで待機(ブロッキング)する。 |
template<F, ...A> run_and_wait(func, args) |
run(func, args); wait(); と等価。個別呼び出しに比べて実行時効率改善の余地がある。 |
“例外リスト処理ハンドラ” にはtask_group::ignore_exceptions
(=タスクから送出された例外を全て無視)、もしくは下記シグネチャをもつ関数オブジェクトを指定する*2。生成タスクから送出された例外オブジェクトは例外リスト(exception_list
)に保持され、task_group
デストラクタにて例外リストが空でないときのみ “例外リスト処理ハンドラ” が呼び出される。なお “例外リスト処理ハンドラ” 自身が送出する例外は無視される(task_group
デストラクタはnoexcept指定されるため)。
void ExceptionHandler(const exception_list&);
TBB/PPLとの差分
task_group
クラスでは “キャンセル機構” を提供しないため、キャンセルしたい場合はタスク処理の一部として記述(協調的キャンセル)する必要がある。TBB/PPLではtask_group
クラスが汎用のキャンセル機構を提供していたが、誤用によるアンチパターンを避けるため削除された。task_group
デストラクタは暗黙的にwait
メンバ関数を呼び出す。TBB/PPLでは明示的にwait
を呼び出す必要があり、未完了タスクが残っている場合はデストラクタから例外送出される。- 生成タスクから送出された全ての例外が補足され、
task_group
デストラクタにて例外リスト処理ハンドラが呼び出される。TBB/PPLではwait
メンバ関数呼び出し時に生成タスクからの例外が1つだけ再送出される(他タスクからの例外は無視される)。 task_group::wait
メンバ関数は戻り値型void
かつ例外送出なし。TBB/PPLではキャンセル状態の返却やタスク送出例外の再送出を行う。- TBB/PPLで提供される
structured_task_group
クラスは削除(task_groupクラスに対して実行時効率向上を目的とする)。
関連URL