TBB 任务在不再递归时被阻塞
TBB task blocked when not recursing any further
struct root: public task
{
root(){}
tbb::task* execute(){
tbb::task_list l;
tbb::task& c = *new(allocate_continuation()) tbb::empty_task;
int count=0;
// do what this task should do
while(condition){
l.push_back(*new(c.allocate_child())root());
++count;
}
if(count){
c.set_ref_count(count);
c.spawn(l);
}
return NULL;
}
};
main(){
tbb::task_scheduler_init s();
root& r = *new(tbb::task::allocate_root())root();
tbb::task::spawn_root_and_wait(r);
return 0;
}
您好,我已经定义了一个 TBB 任务 "root",它会做一些工作,然后在满足 while
循环中的 condition
时进一步递归。如果 while
循环后 count==0
意味着不需要进一步递归,那么我不会生成更多任务。
因为root
任务不需要继续更新,所以我使用tbb::empty_task
作为继续任务。
问题是执行被阻止了。程序无法正常return。目前,我的解决方案是:
if(!count){
l.push_back(*new(c.allocate_child())tbb::empty_task);
c.spawn(l);
c.set_ref_count(1);
}
不过,我认为价格就是性能。我想知道为什么原始代码不起作用。它在延续任务不是空任务的另一种情况下起作用。我不太明白里面的逻辑。感谢您的任何意见。
一个问题是,当 count==0
时,任务 c
丢失,因为它没有子项,也没有生成。取消分配任务的正确方法是调用 tbb::task::destroy
。但是由于您将其分配为延续,因此向 spawn_root_and_wait
发信号通知工作已完成的责任转移到了任务 c
。由于任务丢失,信号也丢失,导致您观察到的死锁。要为 count==0
情况有效地发送信号,只需 return 作为 root::execute()
的结果指向此 c
任务的指针,这类似于执行 spawn(c)
但避免了额外的同步开销。
替代方法是执行 c.parent()->decrement_ref_count()
并手动调用 destroy(c)
。
struct root: public task
{
root(){}
tbb::task* execute(){
tbb::task_list l;
tbb::task& c = *new(allocate_continuation()) tbb::empty_task;
int count=0;
// do what this task should do
while(condition){
l.push_back(*new(c.allocate_child())root());
++count;
}
if(count){
c.set_ref_count(count);
c.spawn(l);
}
return NULL;
}
};
main(){
tbb::task_scheduler_init s();
root& r = *new(tbb::task::allocate_root())root();
tbb::task::spawn_root_and_wait(r);
return 0;
}
您好,我已经定义了一个 TBB 任务 "root",它会做一些工作,然后在满足 while
循环中的 condition
时进一步递归。如果 while
循环后 count==0
意味着不需要进一步递归,那么我不会生成更多任务。
因为root
任务不需要继续更新,所以我使用tbb::empty_task
作为继续任务。
问题是执行被阻止了。程序无法正常return。目前,我的解决方案是:
if(!count){
l.push_back(*new(c.allocate_child())tbb::empty_task);
c.spawn(l);
c.set_ref_count(1);
}
不过,我认为价格就是性能。我想知道为什么原始代码不起作用。它在延续任务不是空任务的另一种情况下起作用。我不太明白里面的逻辑。感谢您的任何意见。
一个问题是,当 count==0
时,任务 c
丢失,因为它没有子项,也没有生成。取消分配任务的正确方法是调用 tbb::task::destroy
。但是由于您将其分配为延续,因此向 spawn_root_and_wait
发信号通知工作已完成的责任转移到了任务 c
。由于任务丢失,信号也丢失,导致您观察到的死锁。要为 count==0
情况有效地发送信号,只需 return 作为 root::execute()
的结果指向此 c
任务的指针,这类似于执行 spawn(c)
但避免了额外的同步开销。
替代方法是执行 c.parent()->decrement_ref_count()
并手动调用 destroy(c)
。