2

我正在使用英特尔 TBB 实现双音排序。使用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_invoketask_group?_ 还是我应该使用其他方法?

提前致谢

4

3 回答 3

4

该程序不会终止,因为它已死锁。您的代码非常接近正确,但问题是 'g' 是指向 task_group 的全局指针,并且您正在执行递归任务分解,这不是混合良好的组合。

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

任务没有完成,因为您在线程和任务之间共享您的 task_group,并且它们都在有效地等待彼此。

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

请注意,我在 PPL 的 msdn 论坛上回答了一个类似的问题,但请记住,task_group、structured_task_group、parallel_invoke 和 parallel_for / parallel_for_each 的语法和语义在 PPL 和 TBB 之间是一致的;使用对您或您的平台有意义的东西。

于 2011-04-20T07:13:39.253 回答
0

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

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

于 2011-03-24T20:34:13.463 回答
0

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

于 2011-03-25T21:43:25.653 回答