我有这样的代码:
#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,它应该能够获得嵌套任务。它们的持续时间足够长。
感谢。
答案 0 :(得分:1)
Taskwait只等待直接子节点,产生除了taskwait构造中的子节点之外的其他任务,但是如果在taskwait之后有大量工作,则风险(很多)会增加taskwait的延迟。如果你想等待所有的孩子+大孩子等,你可以使用#pragma omp taskgroup构造,或者只是在这些情况下省略taskwaits并在单一构造的末尾使用(隐含)障碍。
答案 1 :(得分:0)
根据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中等待。