我想在C ++中执行一个后序树遍历。树可以很深,我不能使用递归(它耗尽堆栈)。相反,我创建了一个std::stack<...>
,它将所有内容放在堆上,并在while循环中遍历树而不是函数调用。这很有效。
现在我想使用TBB并行化整个过程。我想在每个节点上创建一个task_group
,并在每个节点上运行相同的functor
。但是我发现这会遇到与之前的树深度相同的问题:在最深路径的每个节点上运行functor
会从堆栈中消耗掉一些东西,直到整个过程耗尽。 / p>
有没有办法摆脱这个问题?或者我想象整件事; task_group::wait()
背后是否存在一些可以避免此问题的魔法?
答案 0 :(得分:1)
来自TBB文档(关于隐式延续):
因为父块阻塞,所以它的线程堆栈无法弹出。 线程必须小心它需要做什么工作,因为 持续窃取和阻塞可能导致堆栈增长 没有约束。
这与此不完全相同,但它表明TBB没有使用任何堆栈魔法为当前被阻止的任务清空堆栈。这意味着当使用隐式延续时,你会稍后得到堆栈溢出(在多个线程的堆栈中扩展)。
使用显式延续可能会解决问题,但这在很大程度上取决于线程调度程序的内部TBB实现(未记录)。它有可能正常工作 - 唯一可以知道的方法是查看TBB源代码,看看如何处理任务,或者用简单的堆栈编写简单的测试程序,并查看简单的东西是否能够耗尽它。
答案 1 :(得分:0)
只是评论验证您需要使用延续。没有什么神奇的task_group :: wait会阻止它消耗堆栈。
task_group位于ppl中,您可以使用msdn blog中描述的任务延续,并在ppl示例包中提供。