C ++ intel TBB内循环优化

时间:2012-02-15 18:56:49

标签: c++ c++11 parallel-processing tbb parallel-for

我正在尝试使用英特尔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(我试图删除!!!)没有这个问题。

我正在编译:

intel ICC 12.1 at -03 -xHost -mavx

在intel 2500k(4核)上

编辑:我真的可以改变循环的顺序,因为out循环测试需要用基于循环结果的谓词替换。

1 个答案:

答案 0 :(得分: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可确保每个线程完成一项工作,但不保证相同的片段分布;而affinity_partitioner应该有助于此。