0

Intel TBB を使用して内側のループ (3 番目の 2 番目) を並列化しようとしていますが、内側の 2 つのループのサイズが大きい場合にのみ適切な成果が得られます。

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 (これを削除しようとしています!!!) にはこの問題がないことに注意してください。

私はコンパイルしています:

-03 -xHost -mavx のインテル ICC 12.1

Intel 2500k (4 コア)

編集: ループの結果に基づいて out ループ テストを述語に置き換える必要があるため、ループの順序を実際に変更できます。

4

1 に答える 1

1

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

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

  • コンパイラーの最適化の欠如、自動ベクトル化が最初です (OpenMP と TBB のシングルスレッドのパフォーマンスを比較することで確認できます。TBB がはるかに遅い場合、これが最も可能性の高い理由です)。
  • キャッシュミス; 同じデータを 5000 回実行する場合、キャッシュの局所性は非常に重要であり、OpenMP のデフォルトschedule(static)は非常にうまく機能し、毎回まったく同じパーティショニングを決定論的に繰り返しますが、TBB のワーク スチール スケジューラにはかなりのランダム性があります。ブロック範囲の粒度を problem_size/num_threads に等しく設定すると、スレッドごとに 1 つの作業が保証されますが、作業が同じように分散されることは保証されません。そしてそれaffinity_partitionerを助けることになっています。
于 2012-02-16T12:13:31.663 に答える