0
4

2 回答 2

0

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

如果是这样,那么在区域pragma omp barrier内是一个坏主意single,因为只有一个线程将执行代码并等待所有其他线程,这些线程不执行该区域。

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

对于您的尖锐问题:您正在寻找的似乎是OpenMP Secification pgdepend中 Task 构造的子句。169 .

Massimiliano对这个问题的依赖子句以及它是如何工作的有一个很好的解释。

于 2017-06-30T07:55:42.223 回答
0

一旦您了解了那里发生的事情,最后一个示例就没有那么复杂了:每个任务都Tn依赖于前一次迭代T-1_n及其邻居(T-1_n-1T-1_n+1)。这种模式被称为Jacobi 模板。它在偏微分方程求解器中很常见。

正如 Henkersmann 所说,最简单的选择是使用 OpenMP Task 的depend子句:

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
}

如您所见,OpenMP 任务依赖是点对点的,这意味着您不能用数组区域来表达它们。

对于这种特定情况,另一种选择更简洁,是使用屏障间接强制依赖:

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);
  }
}

每次内循环完成时,第二种情况都会执行同步屏障。同步粒度更粗,因为每次外循环迭代只有 1 个同步点。但是,如果stencil函数很长且不平衡,则可能值得使用任务。

于 2017-06-30T08:35:30.243 回答