OpenMP,依赖图

时间:2017-06-30 00:11:43

标签: parallel-processing openmp dependency-graph

我参加了一些旧的OpenMP练习,但是我很难找到解决方案。

目标是编写与依赖图对应的最简单的OpenMP代码。

图表在此处可见:http://imgur.com/a/8qkYb

第一个很简单。

它对应于以下代码:

#pragma omp parallel
{
#pragma omp simple
  {
#pragma omp task
    {
       A1();
       A2();
    }
#pragma omp task
    {
       B1();
       B2();
    }
#pragma omp task
    {
       C1();
       C2();
    }
  }
}

第二个仍然很容易。

#pragma omp parallel
{
#pragma omp simple
  {
#pragma omp task
    {
       A1();
    }
#pragma omp task
    {
       B1();
    }
#pragma omp task
    {
       C1();
    }
#pragma omp barrier
    A2();
    B2();
    C2();
  }
}

现在是最后一个...... 这让我感到很烦恼,因为所有函数调用中依赖项的数量是不相等的。我认为有一个明确说明你应该等待哪个任务,但我找不到我在OpenMP文档中寻找的内容。

如果有人对这个问题有解释,我将非常感激,因为我已经考虑了一个多月了。

2 个答案:

答案 0 :(得分:0)

首先,OpenMP 4.5规范中没有#pragma omp simple。 我假设你的意思是#pragma omp single

如果是这样pragma omp barriersingle区域内是一个坏主意,因为只有一个线程会执行代码并等待所有其他不执行该区域的线程。

此外,在A2的第二个中,B2和C2不再作为任务并行执行。

至于您的实际问题: 您正在寻找的内容似乎是OpenMP Secification pg. 169上任务构造的depend子句。

对于依赖条款以及Massimiliano for this question的工作方式,有一个很好的解释。

答案 1 :(得分:0)

一旦你理解了那里发生了什么,最后一个例子并不复杂:每个任务Tn取决于之前的迭代T-1_n及其邻居(T-1_n-1和{{1} })。此模式称为Jacobi stencil。它在偏微分方程求解器中很常见。

正如Henkersmann所说,最简单的选择是使用OpenMP Task的T-1_n+1子句:

depend

正如您所看到的,OpenMP任务依赖是点对点的,这意味着您无法用数组区域来表达它们。

另一个选择,对于这个特定情况更为清晰,是使用障碍间接地强制执行依赖:

int val_a[N], val_b[N];    
#pragma omp parallel
#pragma omp single
{
int *a = val_a;
int *b = val_b;
for( int t = 0; t < T; ++t ) {
  // Unroll the inner loop for the boundary cases
  #pragma omp task depend(in:a[0], a[1]) depend(out:b[0])
  stencil(b, a, i);

  for( int i = 1; i < N-1; ++i ) {
     #pragma omp task depend(in:a[i-1],a[i],a[i+1]) \
                 depend(out:b[i])
     stencil(b, a, i);
  }

  #pragma omp task depend(in:a[N-2],a[N-1]) depend(out:b[N-1])
  stencil(b, a, N-1);

  // Swap the pointers for the next iteration
  int *tmp = a;
  a = b;
  b = tmp;
}
#pragma omp taskwait
}

每次内循环结束时,第二种情况都会执行同步屏障。在每个外部循环迭代只有1个同步点的意义上,同步粒度更粗糙。但是,如果int a[N], b[N]; #pragma omp parallel for( int t = 0; t < T; ++t ) { #pragma omp for for( int i = 0; i < N-1; ++i ) { stencil(b, a, i); } } 函数很长且不平衡,则可能值得使用任务。