ワークアイテムを並列に処理するテンプレート関数。
#include "tbb/parallel_do.h"
template<typename InputIterator, typename Body> void parallel_do( InputIterator first, InputIterator last, Body body[, task_group_context& group] ); template<typename Container, typename Body> void parallel_do( Container c, Body body[, task_group_context& group] );
parallel_do テンプレートには 2 つの形式があります。
シーケンス形式 parallel_do(first,last,body) は、シーケンス [first,last) の関数オブジェクト・ボディーに適用されます。アイテムは並列に処理されます。追加のワークアイテムは、parallel_do_feeder 型の第 2 引数がある場合、ボディーによって追加できます。body(x) が入力シーケンスまたは parallel_do_feeder::add メソッドによって追加されたすべてのアイテム x について返されると、関数は終了します。
コンテナー形式 parallel_do(c,body) は、parallel_do(std::begin(c),std::end(c),body) と等価です。
入力イテレーターの要件は、ISO C++ 標準の第 24 章で定義されています。以下の表は、Body 型の要件を示しています。
擬似署名 |
意味 |
---|---|
B::operator()( cv-qualifiers T& item, parallel_do_feeder<T>& feeder ) const OR B::operator()( cv-qualifiers T& item, ) const |
item を処理します。parallel_do は、同じボディー・オブジェクトで item が異なる operator() を同時に呼び出します。 フィーダーの署名は、ワークアイテムの追加を許可します。 注意operator() の引数が 1 つの形式と引数が 2 つの形式の両方を定義することはできません。 |
T( const T& ) |
ワークアイテムをコピーします。 |
~T::T() |
ワークアイテムを破棄します。 |
優れたパフォーマンスを得るには、B::operator() を少なくとも 100,000 クロックサイクル実行します。クロックサイクルが少ない場合、parallel_do のオーバーヘッドがパフォーマンスの利点よりも上回ることがあります。
すべてのアイテムがランダムアクセスのない入力ストリームからのアイテムである場合、parallel_do の並列処理はスケーラブルではありません。スケーリングを達成するには、次のいずれかを行います。
ランダムアクセス・イテレーターを使用して入力ストリームを指定します。parallel_for を使用することも検討してください。
ボディーがワークの断片を 2 つ以上追加するようなアルゴリズムを設計します。
task_group_context オブジェクトを渡して、タスクがこのグループで実行されるようなアルゴリズムにすることができます。デフォルトでは、アルゴリズムは自身がバインドされているグループで実行されます。
次のコードは、引数が 2 つの形式の operator() のボディーを示します。
struct MyBody { void operator()(item_t item, parallel_do_feeder<item_t>& feeder ) { for each new piece of work implied by item do { item_t new_item = initializer; feeder.add(new_item); } } };