OpenMP 4.0嵌套任务并行性和GCC 4.9.1

时间:2015-02-16 21:00:57

标签: multithreading gcc g++ openmp g++4.9

我有这样的代码:

#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,它应该能够获得嵌套任务。它们的持续时间足够长。

感谢。

2 个答案:

答案 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中等待。