私有变量与减少 OMP

private variables vs reduction in OMP

我想了解 OMP 如何处理不同的 for 循环声明。我有:

int main()
{
   int i, A[10000]={...};
   double ave = 0.0;
   #pragma omp parallel for reduction(+:ave)
   for(i=0;i<10000;i++){
       ave += A[i];
   }

   ave /= 10000;

   printf("Average value = %0.4f\n",ave);
   return 0;
}

其中 {...} 是从 1 到 10000 的数字。此代码打印正确的值。如果我使用 #pragma omp parallel for private(ave) 而不是 #pragma omp parallel for reduction(+:ave),那么 printf 的结果是 0.0000。我想我明白 reduction(oper:list) 的作用,但想知道它是否可以替代 private 以及如何替代。

所以是的,您可以在没有 reduction 子句的情况下进行归约。但这有一些您必须了解的缺点:

  1. 你必须手工做事,这更error-prone:
    • 声明局部变量以存储局部累加;
    • 正确初始化它们;
    • 积累进去;
    • 使用 critical 构造对初始变量进行最终归约。
  2. 这更难理解和维护
  3. 这可能不太有效...

无论如何,这是一个使用您的代码的示例:

int main() {
   int i, A[10000]={...};
   double ave = 0.0;
   double localAve;

   #pragma omp parallel private( i, localAve )
   {
       localAve = 0;
       #pragma omp for
       for( i = 0; i < 10000; i++ ) {
           localAve += A[i];
       }
       #pragma omp critical
       ave += localAve;
   }

   ave /= 10000;

   printf("Average value = %0.4f\n",ave);
   return 0;
}

这是手动进行归约的经典方法,但请注意,本应声明为 reduction 的变量未在此处声明为 private。变成 private 的是这个变量的局部替代,而全局变量必须保持 shared.