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

and*_*eee 5 c c++ parallel-processing multithreading openmp

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

int var;
#pragma omp parallel private(var)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

#pragma omp parallel
{
    int var;
    ...
}
Run Code Online (Sandbox Code Playgroud)

另外,我想知道私人条款的重点是什么.这个问题已在OpenMP中解释过:局部变量是否自动私有?,但我确信答案是错的 我不喜欢答案,因为即使C89不阻止你在函数中间定义变量,只要它们在作用域的开头(这是自动的输入并行区域的情况).因此,即使对于老式的C程序员来说,这也不应该有任何区别.我是否应该将其视为一种语法糖,它允许在过去的好日子中使用"定义变量 - 在你的功能中开始"的风格?

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

但是因为我对OpenMP很陌生,所以如果没有对它的解释,我不想怀疑它.提前谢谢你的答案!

Z b*_*son 8

这不仅仅是语法糖.OpenMP努力的一个特性是,如果代码不是用OpenMP编译的,则不会更改串行代码.如果不使用OpenMP进行编译,则忽略用作pragma一部分的任何构造.这样做,你可以使用之类的东西private,firstprivaate,collapse,和parallel for不改变你的代码.更改代码可能会影响编译器如何优化代码.

如果你有像这样的代码

int i,j;
#pragma omp parallel for private(j)
for(i = 0; i < n; i++) {
      for(j = 0; j < n; j++) {
   }
}
Run Code Online (Sandbox Code Playgroud)

为此而不的唯一方式privateC89是通过定义改变代码j并行段内例如:

int i,j;
#pragma omp parallel
{
    int j;
    #pragma omp for
    for(i = 0; i < n; i++) {
           for(j = 0; j < n; j++) {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

vector<int> a;
#pragma omp parallel {
    vector<int> a_private = a;
}
Run Code Online (Sandbox Code Playgroud)

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

不过,话虽如此,在实践中我发现经常说我总有需要更改代码,以获得最佳并行结果,所以我通常是在并行部分定义的一切反正不使用的功能,例如private,firstprivate或者collapse(更不用提无论如何,C++中的OpenMP实现经常与非POD斗争,所以通常自己做得更好.