parallel_do テンプレート関数

概要

ワークアイテムを並列に処理するテンプレート関数。

ヘッダー

 #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) の関数オブジェクト body に適用されます。アイテムは並列に処理されます。追加のワークアイテムは、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 型の要件を示しています。

parallel_do Body と T 型の引数に対する要件

擬似署名

意味

 Body::operator()(
   cv-qualifiersopt T referenceopt item,
   parallel_do_feeder<T>& feeder
 ) const
または
 Body::operator()(
   cv-qualifiersopt T referenceopt item
 ) const
				  

ワークアイテムを処理します。parallel_do は、同じボディー・オブジェクトで item が異なる operator() を同時に呼び出します。

item を値または参照 (rvalue 参照を含む) で受け付けます。

feeder の署名は、ワークアイテムの追加を許可します。

注意

operator() の引数が 1 つの形式と引数が 2 つの形式の両方を定義することはできません。

T( const T& )

C++11 からのオプション。ワークアイテムをコピーします。

T( T&& )

C++11 からオプションでサポート。ワークアイテムを移動します。

~T::T()

ワークアイテムを破棄します。

T 型の引数はコピー構築可能、移動構築可能、または両方でなければなりません。型がコピー構築可能でない場合、追加の使用上の制限があります。

  • Body::operator() が引数を値で受け付ける場合、または InputIterator 型が前方イテレーターの要件を満たさない場合、InputIterator を逆参照すると rvalue 参照が生成されます。

  • 追加のワークアイテムは、(例えば、std::move 関数を使用して) rvalue としてフィーダーに渡します。

task_group_context オブジェクトを渡して、タスクがこのグループで実行されるようなアルゴリズムにすることができます。デフォルトでは、アルゴリズムは自身がバインドされているグループで実行されます。

ヒント

優れたパフォーマンスを得るには、Body::operator() を少なくとも 100,000 クロックサイクル実行します。クロックサイクルが少ない場合、parallel_do のオーバーヘッドがパフォーマンスの利点よりも上回ることがあります。

すべてのアイテムがランダムアクセスのない入力ストリームから読み込まれる場合、parallel_do の並列処理はスケーラブルではありません。スケーリングを達成するには、次のいずれかを行います。

  • ランダムアクセス・イテレーターを使用して入力ストリームを指定します。parallel_for を使用することも検討してください。

  • ボディーがワークの断片を 2 つ以上追加するようなアルゴリズムを設計します。

サンプル

次のコードは、引数が 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);
        }
    } 
};
		

関連情報