2012-02-15 16 views
0

インテル®TBBを使用してインナー・ループ(2番目の3番目)を並列化しようとしていますが、インナー2ループのサイズが重要な場合には、C++ intel TBB内部ループの最適化

TBBはメジャーループの繰り返しごとに新しいスレッドを生成しますか? オーバーヘッドを減らす方法はありますか?

tbb::task_scheduler_init tbb_init(4); //I have 4 cores 
tbb::blocked_range<size_t> blk_rng(0, crs_.y_sz, crs_.y_sz/4); 
boost::chrono::system_clock::time_point start =boost::chrono::system_clock::now(); 
for(unsigned i=0; i!=5000; ++i) 
{ 
    tbb::parallel_for(blk_rng, 
    [&](const tbb::blocked_range<size_t>& br)->void 
    { 
    ::: 

(私が削除しようとしています!!!)OpenMPのは、この問題を持っていないことに注意することは興味深いかもしれません。

私がコンパイルしています

:インテル2500K(4つのコア)

EDITで-03 -xHost -mavx

インテルICC 12.1:私は本当に、ループの順序を変更することができ、アウトループテストはループ結果に基づく述語で置き換える必要があるためです。

+0

これは、並列の作品を5000回生成するよう求めているようですが、それは正確ですか? – user7116

+0

@sixlettervariablesはい、私はopenMPで大きな利益を得ました。私はTBBでこのような利益を再現できるかどうかを知りたいと思います。 – 111111

+2

tbbのパーティショナーを使用してください。特にそうでない場合はaffinity_partiionerを使用してください。 OpenMP固定パーティショニングは、スレッドチームに適用されるポリシーのため、小さな内部ループでは本当にうまくいきます。 – Rick

答えて

1

いいえ、TBBはすべての呼び出しに対して新しいスレッドを生成しません。parallel_forです。実際には、新しいスレッドチームを開始する可能性のあるOpenMP並列領域とは異なり、TBBはすべてtask_scheduler_initオブジェクトが破棄されるまで同じスレッドチームで作業します。暗黙的な初期化(task_scheduler_initは省略)の場合、同じワーカースレッドがプログラムの最後まで使用されます。

したがって、パフォーマンスの問題は他の何かによって引き起こされます。私の経験から、最も可能性が高い理由は、以下のとおりです。コンパイラの最適化の

  • 不足、自動ベクトル化は、最初(のOpenMPおよびTBBのシングルスレッドの性能を比較することで確認することができますされている; TBBが非常に遅い場合は、この最も可能性の高い理由です)。
  • キャッシュミス;同じデータを5000回実行すると、キャッシュのローカリティが非常に重要になり、OpenMPのデフォルトのschedule(static)は非常にうまく動作し、TBBのワークスティールスケジューラはかなりのランダム性を持ちます。 blocked_range粒度をproblem_size/num_threadsに設定すると、スレッドごとに1つの作業が保証されますが、ピースの分布は同じであるとは限りません。 affinity_partitionerがそれを手助けすることになっています。