我有一个这样的代码:
#pragma omp parallel
{
#pragma omp single
{
int x;
#pragma omp task depend(inout:x)
{
for (int i = 1; i < 16; i++)
{
#pragma omp task
DoComputationOnPartition(i);
}
#pragma omp taskwait
}
for (int i = 1; i < 16; i++)
{
#pragma omp task depend(in:x)
{
OperateOnPartition(i);
}
}
#pragma omp task depend(inout:x)
{
for (int i =1; i < 16; i++) x++;
}
for (int i = 1; i < 16; i++)
{
#pragma omp task depend(in:x)
{
OperateOnPartition(i);
}
}
#pragma omp taskwait
}
}
我发现主线程永远无法执行嵌套在第一个任务中的DoComputationOnPartition任务。有人能解释一下吗?它应该起作用,对吧?#pragma omp taskwait是一个调度点,因此团队的任何线程都应该能够获得任务。主线程到达最后一个taskwait,它应该能够获得嵌套任务。它们的持续时间足够长。
谢谢。
Taskwait只等待直接的子任务,在Taskwait构造中可能会生成除子任务之外的其他任务,但如果在taskwaite之后有大量工作,则有增加Taskwait延迟的风险。如果你想等待所有的children+grand-children等,你可以使用#pragma omp taskgroup构造,或者在这些情况下省略taskwaits,在单个构造的末尾使用(隐式)屏障。
根据OpenMP 4.0规范:
绑定任务组区域绑定到当前任务区域。任务组区域的绑定线程集是当前团队。
描述当线程遇到任务组构造时,它开始执行区域。有一个隐含的任务调度位于任务组区域末尾的点。当前任务是在任务调度点挂起,直到它的所有子任务在任务组区域及其所有派生任务中生成完全执行。
所以,你的意思是把任务放在一个任务组里。好吧。但它也意味着一个调度点,和taskwait一样。如果libgomp对此有问题,那么这是特定于该运行时的问题,而不是作为API的OpenMP。ICC和其他像OmpS这样的运行时没有这样的行为问题:-S
只有当您想等待所有任务层次结构时,任务组才有意义(在我看来),但事实并非如此。
我想你是这个意思,对吧?:
#pragma omp task depend(inout:x)
{
#pragma omp taskgroup
{
for (int i = 1; i < 16; i++)
{
#pragma omp task
DoComputationOnPartition(i);
}
}
}
原始代码在另一个上下文中嵌套了第一个taskwait,因此该taskwait中只有一小群任务在等待。