OpenMP 4中的任务依赖性

10
以下代码基于OpenMP 4.0规范工作:
out和inout依赖类型。生成的任务将是所有之前生成的兄弟任务的依赖任务,这些任务引用了in、out或inout依赖类型列表中的至少一个列表项。
这意味着任务3成为任务2的依赖任务。但这没有意义!为什么一个输入输出依赖的任务要成为一个输入依赖任务的依赖任务呢?
那么,我需要做什么来使它们独立? p.s:在Linux上使用g++ 4.9测试过代码。
#include <stdio.h>
#include <omp.h>
#include <unistd.h>
int main() {
int x,y;
#pragma omp parallel num_threads(10)
{
#pragma omp single nowait
 {
#pragma omp task depend (out:x)  //task1
  {
        x=1;
  }
#pragma omp task depend(in:x) depend(out:y)  //task2
  {
        sleep(2); //Does task3 wait for us? Yes!
        y=x+1;
  }
#pragma omp task depend (inout:x)  //task3
  {
        x++;
        printf("task3(x): %d\n" , x);
  }
#pragma omp task depend (in:x,y)  //task4
 {
        printf("task4 (x+y): %d\n" , x+y);
 }
 }
}
return 0;
}
1个回答

19

问题1:这意味着任务3变成了任务2的依赖项。对吗?

根据OpenMP 4.0关于depend子句(重点是我的)的标准:

任务依赖关系源自depend子句及其列表项的依赖类型,其中依赖类型为以下之一:

in 依赖类型。生成的任务将成为所有以前生成的兄弟任务的依赖任务,这些兄弟任务中至少有一个引用out或inout依赖类型列表中的一个列表项。

out和inout 依赖类型。生成的任务将成为所有以前生成的兄弟任务的依赖任务,这些兄弟任务中至少有一个引用in、out或inout依赖类型列表中的一个列表项。

从中可以得出以下结论:

  • 子句depend(in:x)将生成一个任务,该任务依赖于先前生成的所有带有depend(out:x)depend(inout:x)的任务
  • 子句depend(out:x)depend(inoout:x)将生成一个任务,该任务依赖于先前生成的所有提到x的任务的depend子句

将此应用于您特定的情况会得到这种依赖关系链:

       task1 (out:x) -> task2 (in:x,out:y) -> task4 (in:x,y)
                                   |            ^
                                   |            |
                                   > task3 (inout:x)   

因此,任务3取决于任务2的完成。


问题2为什么输入输出依赖任务要成为输入依赖任务的依赖项?

我只想提醒您,按照这个规则,运行结束时您的变量xy将具有确定性值(假设您注意同步访问内存)。如果任务3依赖于任务1而不是任务2,则这种确定性将无法保持(并且inout依赖关系等效于in依赖关系)。


问题3我需要做什么才能使它们独立?

inout:x依赖关系转换为in:x依赖关系,并通过atomic子句同步访问x。这样,运行结果可能是:

  • x == 2y == 2
  • x == 2y == 3

具体取决于任务2是否在任务3之前执行。


3
非常好的解释。谢谢!因此,最终这意味着输入和输出被同等对待。是吗?它们可以互换使用! - towi_parallelism
@towi_parallelism 我认为你对于 inout 和 out 的行为是正确的。即使在 OpenMP 5.0 规范中,我也找不到 inout 与 out 有什么不同的地方,说实话。 - Animesh Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接