2

我有这样的代码:

#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 是一个调度点,因此团队的任何线程都应该能够获得任务。主线程到达最终任务等待,它应该能够获得嵌套任务。他们有足够长的时间来允许这样做。

谢谢。

4

2 回答 2

1

Taskwait 只等待直接的子代,在 taskwait 构造中产生除子代之外的其他任务是可能的,但是如果您在 taskwait 之后有大量工作,则有可能(很大)增加 taskwait 的延迟。如果您想等待所有孩子 + 大孩子等,您可以使用 #pragma omp taskgroup 构造,或者只是在这些情况下省略任务等待并在单个构造的末尾使用(隐式)屏障。

于 2015-11-16T08:17:46.027 回答
0

根据 OpenMP 4.0 规范:

绑定任务组区域绑定到当前任务区域。任务组区域的绑定线程集是当前团队。

描述当线程遇到任务组构造时,它开始执行该区域。在任务组区域的末端有一个隐式的任务调度点。当前任务在任务调度点挂起,直到它在任务组区域中生成的所有子任务及其所有后代任务完成执行。

因此,您的意思是将任务放在任务组中。好吧,好吧。但它也意味着一个调度点,和taskwait一样。如果 libgomp 有问题,那是该运行时特有的问题,而不是 OpenMP 作为 API。ICC 和 OmpSs 等其他运行时没有这样的行为问题:-S

任务组仅在您想等待所有任务层次结构时才有意义(如我所见),但事实并非如此。

我想你是这个意思,对吧?

 #pragma omp task depend(inout:x)
 {
        #pragma omp taskgroup
        {
            for (int i = 1; i < 16; i++)
            {
                 #pragma omp task
                 DoComputationOnPartition(i);
            }
        }
  }

原始代码将第一个 taskwait 嵌套在另一个上下文中,因此只有一小部分任务在该 taskwait 中等待。

于 2015-11-17T13:58:05.760 回答