C++英特尔TBB内部循环优化

C++ intel TBB inner loop optimisation

本文关键字:循环 优化 内部 TBB 英特尔 C++      更新时间:2023-10-16

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

我正在编译:

intel ICC 12.1 at-03-xHost-mavx

在英特尔2500k(4核)上

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

否,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可以确保每个线程有一个工件,但不能保证工件的分布相同;而CCD_ 5应该对此有所帮助