我正在尝试使用英特尔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循环测试需要用基于循环结果的谓词替换。
答案 0 :(得分:1)
不,TBB不会为parallel_for
的每次调用生成新线程。实际上,与每个可以启动新线程团队的OpenMP并行区域不同,TBB使用相同的线程团队,直到所有task_scheduler_init
个对象都被销毁;如果是隐式初始化(省略task_scheduler_init
),则使用相同的工作线程直到程序结束。
因此性能问题是由其他原因造成的。根据我的经验,最可能的原因是:
schedule(static)
非常有效,每次确定性地重复完全相同的分区,而TBB的工作窃取调度程序具有显着的随机性。将blocked_range粒度设置为等于problem_size / num_threads可确保每个线程完成一项工作,但不保证相同的片段分布;而affinity_partitioner
应该有助于此。