2012-02-15 101 views
0

我試圖使用英特爾TBB並行內部循環(3的第二)但是,當內部2循環的大小顯着時,我只得到體面的回報。C++英特爾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(我試圖刪除!!!)沒有這個問題可能很有趣。

我與編譯:

英特爾ICC 12.1在-03 -xHost -mavx

在一個英特爾2500K(4個核)

編輯:我真的可以改變循環的順序,因爲out循環測試需要用基於循環結果的謂詞來替換。

+0

看來你要求它產生5000次並行工作,這是否準確? – user7116 2012-02-15 19:30:04

+0

@sletterlettervariables是的,我用openMP獲得了很大的收益,我想知道是否可以使用TBB – 111111 2012-02-15 19:58:25

+2

嘗試使用tbb中的分區程序來複制這樣的增益,尤其是affinity_partiioner(如果沒有)。 OpenMP固定分區真的很適合小內部循環,因爲它適用於線程團隊的策略... – Rick 2012-02-15 22:15:30

回答

1

不,TBB不會爲每次調用parallel_for產生新的線程。實際上,與OpenMP並行區域不同,它們都可以啓動一個新的線程組,TBB與同一個線程組一起工作,直到所有的對象都被銷燬;並且在隱式初始化的情況下(省略task_scheduler_init),直到程序結束時使用相同的工作線程。

所以性能問題是由別的東西引起的。最有可能的原因,從我的經驗,主要有:

  • 缺乏編譯器優化,自動矢量被第一個(可以通過比較OpenMP和TBB的單線程性能檢查;如果TBB慢得多,那麼這是最可能的原因)。
  • 緩存未命中;如果5000次運行相同的數據,則緩存區域具有非常重要的意義,並且OpenMP的默認schedule(static)工作得很好,每次確定性地重複完全相同的分區,而TBB的工作竊取調度程序具有顯着的隨機性。設置blocked_range顆粒大小等於problem_size/num_threads可以確保每個線程有一個工作,但不能保證工件的分配相同; affinity_partitioner應該有助於這一點。