e在这里取哪个值?
Which value does e take here?
我有以下一段代码(注意:这是为了帮助我理解这个概念,所以它是一个示例代码,不是我想要的 运行)
List ml; //my_list
Element *e;
#pragma omp parallel
#pragma omp single
{
for(e=ml->first;e;e=e->next)
#pragma omp task
process(e);//random function
}
有人提到 e 将始终具有相同的值,我正在思考为什么会这样以及该值是多少。
我的try/reasoning:
e 的值在 pragma omp single
内部发生变化,这些变化不会在任务内部执行(如果我没记错的话,单个区域的值不会被带到任务内部,除非我使用某些东西像 firstprivate(e)
,此外,它将采用的值将是随机的,因为我们没有将 e 初始化为单个和并行 omp 区域之外的任何变量,并且如果我们在外部初始化为例如一个值 x 那么 e 将永远是 x
如能帮助纠正或验证我的推理,我们将不胜感激。
我已经为您的示例添加了一些注释,希望能使行为更加清晰。
List ml; //my_list
Element *e;
#pragma omp parallel // e is shared for the parallel region
#pragma omp single
{
for(e=ml->first;e;e=e->next)
#pragma omp task // since e is shared, all tasks will see the "same" e
process(e);
}
这是怎么回事(由上面的评论指出):您在 parallel
构造的范围之外声明 e
。根据 OpenMP 规范,该变量将在所有执行的线程之间共享。 single
构造然后将执行限制为团队中的任何一个线程(e
仍然在所有线程之间共享,请参阅 https://www.openmp.org/spec-html/5.1/openmpsu113.html#x148-1600002.21.1)。
当挑选的线程遇到task
构造时,OpenMP规范要求task
创建的任务继承e
变量(共享)的共享属性,因此所有创建的任务都将看到相同的变量,并且选择的线程在执行 for
循环时可能会覆盖 e
变量。
这就是 firstprivate(e)
的用武之地:
List ml; //my_list
Element *e;
#pragma omp parallel // e is shared for the parallel region
#pragma omp single
{
for(e=ml->first;e;e=e->next)
#pragma omp task firstprivate(e) // task now receives a private "copy" of e
process(e);
}
在这里,创建任务将具有e
的私有副本,该副本以当前值的初始化为e
,因为挑选的线程通过for
loop。[= = 29=]
解决此问题的另一种方法是:
List ml; //my_list
#pragma omp parallel
#pragma omp single
{
Element *e; // e is thread-private inside the parallel region
for(e=ml->first;e;e=e->next)
#pragma omp task // task now receives a private "copy" of e w/o firstprivate
process(e);
}
因为在这个例子中,OpenMP 规范要求变量应该被视为您指定了 firstprivate(e)
(参见 https://www.openmp.org/spec-html/5.1/openmpsu113.html#x148-1610002.21.1.1)。
我有以下一段代码(注意:这是为了帮助我理解这个概念,所以它是一个示例代码,不是我想要的 运行)
List ml; //my_list
Element *e;
#pragma omp parallel
#pragma omp single
{
for(e=ml->first;e;e=e->next)
#pragma omp task
process(e);//random function
}
有人提到 e 将始终具有相同的值,我正在思考为什么会这样以及该值是多少。
我的try/reasoning:
e 的值在 pragma omp single
内部发生变化,这些变化不会在任务内部执行(如果我没记错的话,单个区域的值不会被带到任务内部,除非我使用某些东西像 firstprivate(e)
,此外,它将采用的值将是随机的,因为我们没有将 e 初始化为单个和并行 omp 区域之外的任何变量,并且如果我们在外部初始化为例如一个值 x 那么 e 将永远是 x
如能帮助纠正或验证我的推理,我们将不胜感激。
我已经为您的示例添加了一些注释,希望能使行为更加清晰。
List ml; //my_list
Element *e;
#pragma omp parallel // e is shared for the parallel region
#pragma omp single
{
for(e=ml->first;e;e=e->next)
#pragma omp task // since e is shared, all tasks will see the "same" e
process(e);
}
这是怎么回事(由上面的评论指出):您在 parallel
构造的范围之外声明 e
。根据 OpenMP 规范,该变量将在所有执行的线程之间共享。 single
构造然后将执行限制为团队中的任何一个线程(e
仍然在所有线程之间共享,请参阅 https://www.openmp.org/spec-html/5.1/openmpsu113.html#x148-1600002.21.1)。
当挑选的线程遇到task
构造时,OpenMP规范要求task
创建的任务继承e
变量(共享)的共享属性,因此所有创建的任务都将看到相同的变量,并且选择的线程在执行 for
循环时可能会覆盖 e
变量。
这就是 firstprivate(e)
的用武之地:
List ml; //my_list
Element *e;
#pragma omp parallel // e is shared for the parallel region
#pragma omp single
{
for(e=ml->first;e;e=e->next)
#pragma omp task firstprivate(e) // task now receives a private "copy" of e
process(e);
}
在这里,创建任务将具有e
的私有副本,该副本以当前值的初始化为e
,因为挑选的线程通过for
loop。[= = 29=]
解决此问题的另一种方法是:
List ml; //my_list
#pragma omp parallel
#pragma omp single
{
Element *e; // e is thread-private inside the parallel region
for(e=ml->first;e;e=e->next)
#pragma omp task // task now receives a private "copy" of e w/o firstprivate
process(e);
}
因为在这个例子中,OpenMP 规范要求变量应该被视为您指定了 firstprivate(e)
(参见 https://www.openmp.org/spec-html/5.1/openmpsu113.html#x148-1610002.21.1.1)。