我正在尝试使用Intel TBB并行化一个内部循环(第2个,共3个),但是,当内部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(我要删除它!!)没有这个问题。

我正在编译:

英特尔ICC 12.1 at -03 -xHost -mavx

在2500k Intel(4核)上

编辑:我真的可以更改循环的顺序,因为需要根据循环结果用谓词替换循环外测试。

最佳答案

不,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应该可以帮助您。

关于c++ - C++ Intel TBB内部循环优化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9299474/

10-13 05:00