私有子句中的变量与OpenMP中并行区域中定义的变量之间是否存在任何差异?

时间:2014-05-27 13:18:02

标签: c++ c multithreading parallel-processing openmp

我想知道是否有任何理由更喜欢OpenMP中的private(var)子句而不是(私有)变量的本地定义,即

int var;
#pragma omp parallel private(var)
{
    ...
}

VS

#pragma omp parallel
{
    int var;
    ...
}

另外,我想知道那时私人条款的重点是什么。这个问题在OpenMP: are local variables automatically private?中得到了部分解释,但是我不喜欢这个答案,因为即使是C89也不会禁止你在函数中间定义变量,只要它们在一个开头就可以了。范围(进入并行区域时自动出现)。因此,即使对于老式的C程序员来说,这也不应该有任何区别。 我是否应该将其视为语法糖,它允许在你的功能开始时定义变量"定义变量。在过去的美好时光中使用的风格?

顺便说一下:在我看来,第二个版本也阻止程序员在并行区域之后使用私有变量,希望它可能包含一些有用的东西,所以另一个-1用于私有子句。

但是,由于我对OpenMP很陌生,所以我不想在没有好的解释的情况下怀疑事情。提前感谢您的回答!

1 个答案:

答案 0 :(得分:8)

这不仅仅是语法糖。 OpenMP努力的一个特性是如果代码不是用OpenMP编译的话就不要改变串行代码。如果不使用OpenMP进行编译,则忽略用作pragma一部分的任何构造。这样做可以在不更改代码的情况下使用privatefirstprivaatecollapseparallel for之类的内容。更改代码可能会影响编译器如何优化代码。

如果你有像

这样的代码
int i,j;
#pragma omp parallel for private(j)
for(i = 0; i < n; i++) {
      for(j = 0; j < n; j++) {
   }
}

private中没有C89的唯一方法是通过在并行部分中定义j来更改代码,例如:

int i,j;
#pragma omp parallel
{
    int j;
    #pragma omp for
    for(i = 0; i < n; i++) {
           for(j = 0; j < n; j++) {
        }
    }
}

这是一个带有firstprivate的C ++示例。假设你有一个你想要私有的向量。如果使用firstprivate,则不必更改代码,但如果在并行区域内声明私有副本,则会更改代码。如果在没有OpenMP的情况下进行编译,则会生成不必要的副本。

vector<int> a;
#pragma omp parallel {
    vector<int> a_private = a;
}

此逻辑适用于许多其他构造。例如collapse。您可以手动融合更改代码的循环,或者可以使用collapse并仅在使用OpenMP编译时将其融合。

然而,说了这么多,实际上我经常发现我需要更改代码以获得最佳的并行结果,所以我通常在并行部分中定义所有内容并且不使用诸如{{1}之类的功能},privatefirstprivate(更不用说C ++中的OpenMP实现经常会遇到non-POD anyway,所以通常自己做得更好。)