OpenMP 4 中的任务依赖
以下代码基于 OpenMP 4.0 规范:
The following code works based on the OpenMP 4.0 specification:
out 和 inout 依赖类型.生成的任务将是所有先前生成的兄弟任务的依赖任务引用 in、out 或 inout 中的至少一个列表项依赖类型列表.
The out and inout dependence-types. The generated task will be a dependent task of all previously generated sibling tasks that reference at least one of the list items in an in, out, or inout dependence-type list.
这意味着 task3 变得依赖于 task2.对?但这没有意义!为什么输入输出依赖任务应该是输入依赖任务的依赖?
This means that task3 becomes dependent of task2. Right? but it does not make sense! Why should an input-output dependency task be a dependent of an input dependency task?
我需要做什么才能让他们独立?p.s:在 Linux 上使用 g++ 4.9 测试的代码.
What do I need to do in order to make them independent? p.s: code tested with g++ 4.9 on Linux.
#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
" , x);
}
#pragma omp task depend (in:x,y) //task4
{
printf("task4 (x+y): %d
" , x+y);
}
}
}
return 0;
}
推荐答案
问题 1 :这意味着 task3 变得依赖于 task2.对吗?
根据OpenMP 4.0标准上的depend
子句(强调我的):
According to the OpenMP 4.0 standard on the depend
clause (emphasis mine):
任务依赖来源于depend
的依赖类型子句及其列表项,其中依赖类型是其中之一以下:
Task dependences are derived from the dependence-type of a
depend
clause and its list items, where dependence-type is one of the following:
in 依赖类型.生成的任务将是一个依赖 所有先前生成的兄弟任务的任务,这些任务引用了out 或 inout 依赖类型中的至少一个列表项列表.
The in dependence-type. The generated task will be a dependent task of all previously generated sibling tasks that reference at least one of the list items in an out or inout dependence-type list.
out 和 inout 依赖类型.生成的任务将是依赖于的所有先前生成的兄弟任务,这些任务至少引用了一个列表项中的一个输入、输出或输入依赖类型列表.
The out and inout dependence-types. The generated task will be a dependent task of all previously generated sibling tasks that reference at least one of the list items in an in, out, or inout dependence-type list.
从这个描述如下:
- 子句
depend(in:x)
将生成一个依赖于所有先前使用depend(out:x)
或depend(inout) 生成的任务的任务:x)
- 子句
depend(out:x)
或子句depend(inoout:x)
将生成一个依赖于所有先前生成的提到x 的任务的任务
在depend
子句中
- the clause
depend(in:x)
will generate a task dependent on all the previously generated tasks withdepend(out:x)
ordepend(inout:x)
- the clause
depend(out:x)
or the clausedepend(inoout:x)
will generate a task dependent on all the previously generated tasks mentioningx
in adepend
clause
将其应用于您的特定情况会产生这样的依赖链:
Applying this to your specific case gives a chain of dependencies of this kind:
task1 (out:x) -> task2 (in:x,out:y) -> task4 (in:x,y)
| ^
| |
> task3 (inout:x)
因此task3依赖task2的完成.
问题 2:为什么输入-输出依赖任务应该是输入依赖任务的依赖?
我只想让您注意到,使用此规则,您将在运行结束时获得变量 x
和 y
的确定性值(假设您小心同步访问内存).如果 task3 依赖于 task1 而不是 task2,则此确定性将不成立(并且 inout
依赖项将等同于 in
依赖项).
I would just let you notice that with this rule you will have a deterministic value of your variables x
and y
at the end of the run (assuming you take care of synchronizing accesses to memory). If task3 was dependent on task1 instead of task2, this determinism wouldn't hold (and an inout
dependency would have been equivalent to an in
dependency).
问题 3:我需要做什么才能让他们独立?
将 inout:x
依赖转换为 in:x
依赖,并通过 atomic
同步对 x
的访问条款.这样你就可以运行:
Turn the inout:x
dependency into an in:x
dependency and synchronize accesses to x
via atomic
clauses. That way you will have runs in which either:
x == 2
和y == 2
x == 2
和y == 3
x == 2
andy == 2
x == 2
andy == 3
取决于 task2 是否在 task3 之前执行.
depending on whether task2 executes before task3 or not.
相关文章