2

トークンの処理を並列化するためにtbbパイプラインを使用したいと思います。

ただし、中間フィルター中にトークンの割り当てを解除して再割り当てする必要はありません。単にその場で変更して返却しても大丈夫ですか?たとえば、私がやりたいことは次のとおりです。

class MiddleFilter
{
SomeClass* operator() (SomeClass* input)
{
input->somevalue *= 2;
return input;
}
}

と電話

tbb::parallel_pipeline(nbtoken, someinputfilter 
& tbb::make_filter<SomeClass*, SomeClass*>(tbb::filter::parallel, MiddleFilter())
& someoutputfilter)

SomeClass入力および出力フィルターで割り当てられ、解放されます。

4

1 に答える 1

3

はい、フィルターに渡されたオブジェクトのインプレース変更が許可されており、コピーにコストがかかるオブジェクトを処理する場合によく役立ちます。これは、Bzip2をparallel_pipelineで並列化するときに行いました。TBBに関する限り、この例のポインタ「入力」は、TBBが解釈しようとしない値にすぎません。

最初/最後のフィルターで割り当て/解放を保存するために時々使用する別のトリックがあります。最初と最後のフィルターがシリアルフィルターであり、最初のフィルターが最後のフィルターが消費するのと同じタイプのオブジェクトを生成する場合、オブジェクトの循環キューを使用してオブジェクトをリサイクルできます。バッファーのサイズはmax_number_of_live_tokens(parallel_pipelineの最初のパラメーター)である必要があります。最初のフィルターは、デキューすることによってオブジェクトを割り当てることができます。最後のステージでは、オブジェクトをキューに入れることで解放できます。max_number_of_live_tokensのキューから始めます。トークン制限は、キューがアンダーフローまたはオーバーフローしないことを保証します。

きちんとした部分は、循環キューが簡単なシリアルコードを使用して実装できることです。尾/頭の配列と2つのポインタで十分です。アトミック操作、ロック、またはメモリフェンスは必要ありません。アンダーフロー/オーバーフローがないことが保証されているということは、テールポインターをバンプするだけで(そして幸いにもヘッドポインターを無視することで)エンキュー操作を実装できることを意味します。また、deque操作の場合はその逆です。呼び出し元はシリアルフィルターであるため、ロックは必要ありません。さらに悪いことに、テールポインターとヘッドポインターの両方が同時に、しかし独立してぶつかります。TBBがメモリフェンシングを処理します。

于 2013-03-01T22:19:03.753 に答える