private variables vs reduction in OMP

Peter Hristov Source

I am trying to understand how OMP treats different for loop declarations. I have:

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;
}

where {...} are the numbers form 1 to 10000. This code prints the correct value. If instead of #pragma omp parallel for reduction(+:ave) I use #pragma omp parallel for private(ave) the result of the printf is 0.0000. I think I understand what reduction(oper:list) does, but was wondering if it can be substituted for private and how.

copenmppragma

Answers

answered 3 months ago Gilles #1

So yes, you can do reductions without the reduction clause. But that has a few downsides that you have to understand:

  1. You have to do things by hand, which is more error-prone:
    • declare local variables to store local accumulations;
    • initialize them correctly;
    • accumulate into them;
    • do the final reduction in the initial variable using a critical construct.
  2. This is harder to understand and maintain
  3. This is potentially less effective...

Anyway, here is an example of that using your code:

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;
}

This is a classical method for doing reductions by hand, but notice that the variable that would have been declared reduction isn't declared private here. What becomes private is a local substitute of this variable while the global one must remain shared.

comments powered by Disqus