我有一个关于OpenMP的非常奇怪的问题。对于下面的示例,默认情况下,变量“a”应根据OpenMP规则进行“共享”(章节:2.9.1.2:区域中引用的变量的数据共享属性规则,但不包含在构造中:具有动态的对象)存储持续时间是共享的)。当我运行它时,我得到:
adre1: 0x7f51640008c0
adre2: 0x7f51640008c0
adre3: 0x1122d40
adre4: 0x7f51640008c0
这是有道理的。
void jl()
{
char *a=(char *)malloc(10);
printf("adre1: %p\n",a);
#pragma omp task
{
printf("adre2: %p\n",a);
a=(char *)malloc(10);
printf("adre3: %p\n",a);
}
#pragma omp taskwait
printf("adre4: %p\n",a);
}
但是如果我在这样的任务后添加“共享”:
void jl()
{
char *a=(char *)malloc(10);
a[1]='c';
printf("adre1: %p\n",a);
#pragma omp task shared(a)
{
printf("adre2: %p\n",a);
a=(char *)malloc(10);
printf("adre3: %p\n",a);
}
#pragma omp taskwait
printf("adre4: %p\n",a);
}
输出是:
adre1: 0x1cefd40
adre2: 0x1cefd40
adre3: 0x7f93d00008c0
adre4: 0x7f93d00008c0
我在这里很困惑。当你在任务中重定向变量“a”的地址时,看到它在外面是可见的,但我在Openmp中找不到这样的数据属性规则。
这两种情况有什么区别?
答案 0 :(得分:1)
第一种情况中的a
变量为firstprivate
。如果没有其他规则适用,这是task
构造中引用的变量的默认隐式确定的数据共享属性。实际上,如果你遵守规则(见§2.9.1.1)并逐一审阅,你就会看到其他规则都不适用:
- 在
parallel
或task
构造中,这些变量的数据共享属性是 由default
子句确定(如果存在)。
不是这种情况,因为default
构造中没有task
子句。
- 在
parallel
构造中,如果不存在default
子句,则这些变量是 共享。
不是parallel
构造。
- 对于
task
以外的构造,如果不存在default
子句,则为这些变量 从封闭的上下文继承他们的数据共享属性。
同样,这是一个task
构造,规则不适用。
- 在
task
构造中,如果不存在default
子句,则为...中的变量 确定封闭上下文由绑定到当前的所有隐式任务共享 团队是共享的。
a
是一个具有自动存储持续时间的变量,在被调用的例程中声明。因此,其数据共享属性被预先确定为私有(参见§2.9.1.2),该规则不适用。
- 在
task
构造中,如果不存在default
子句,则为数据共享的变量 属性不是由上面的规则确定的firstprivate。
这个包罗万象的规则是唯一适用的规则。
Firstprivate变量最初取外部变量的值,但对它们的任何更改在构造/区域外都不可见。这与OpenMP任务一样,就像闭包一样 - 任务在创建时捕获变量的值,并在执行任务时稍后使用这些值。
答案 1 :(得分:-1)
答案取决于编译器, 在某些实现中,默认共享= firstprivate而在其他实现(包括我的)默认=共享,
例如: void main() {
char *a=(char *)malloc(10);
printf("adre1: %p\n",a);
omp_set_num_threads(1);
#pragma omp parallel
{
//#pragma omp single
{
#pragma omp task firstprivate(a)
{
printf("adre2: %p\n",a);
a=(char *)malloc(10);
printf("adre3: %p\n",a);
}
#pragma omp taskwait
printf("adre4: %p\n",a);
}
printf("adre5: %p\n",a);
}
printf("adre6: %p\n",a);
}
输出:
如果我们改变#pragma omp task firstprivate(a)==> #pragma omp task shared(a)
将来为了避免与数据共享相关的混淆,请始终使用:
#pragma omp parallel default(none)
{
//my code
}.