英特尔TBB使用task_group进行Bitonic排序

时间:2011-03-23 10:48:25

标签: c++ sorting tbb

我正在使用intel TBB实现一种bitonic排序。使用 parallel_invoke 方法时一切顺利。但是当使用task_group(不调用wait方法)时,输出不会被排序。当如下使用task_group时,程序不会终止。

void bitonic_merge(bool up, int array[],int size){
  if(size==1){
      return;
  }
  int m = greatestPowerOfTwoLessThan(size);
  bitonic_compare(up, array, size - m, m);
  g->run(Bitonic_Merge(up, array , m));
  g->run(Bitonic_Merge(up, &array[m],size - m));
  g->wait();
  return;    
}

有人能看出什么问题吗? parallel_invoke和使用task_group有什么区别?还有什么比这种情况更好用? parallel_invoke task_group ?或者我应该使用其他方法吗?

提前致谢

3 个答案:

答案 0 :(得分:4)

程序没有终止,因为它已死锁。你的代码非常接近正确,但问题是'g'是一个指向task_group的全局指针,你进行递归任务分解,这不是一个混合得很好的组合。

如果你闯入调试器,我希望你会在task_group :: wait中看到很多线程,等待任务完成。

任务没有完成,因为你在线程和任务中共享你的task_group,而且他们都在有效地等待彼此。

要解决此问题,请在bitonic_merge函数内的堆栈上声明task_group(或structured_task_group),这仍然允许在等待调用期间调度和执行任务,就像使用parallel_invoke一样,但是因为task_group不是'在任务之间共享,等待调用将在所有子任务完成后完成并避免死锁。

请注意,我在msdn论坛上为PPL回答了similar question with a performance slant并记住了task_group,structured_task_group,parallel_invoke和parallel_for / parallel_for_each的语法和语义在PPL和TBB之间是一致的。使用对你或你的平台有意义的东西。

答案 1 :(得分:0)

如果子问题的数量不变,请使用tbb :: parallel_invoke。 否则使用递归和task_group。 由于子问题的数量是2,因此parallel_invoke适合并且更容易实现。

有关详细信息,请参阅英特尔TBB设计模式

答案 2 :(得分:0)

在这里等待任务组非常重要。如果没有wait(),函数将在完成task_group :: run()完成的递归“调用”之前返回,显然它会破坏算法。 parallel_invoke确实适用,并且它会自动等待“调用”函数完成,因此更易于使用。 是什么让我(作为TBB开发人员)担心的是为什么给定的程序片段不会终止。就我所知,它应该运作良好。你介意提交一个完整的程序源(在这里或the TBB forum?)