Reduction clause using * instead of + returns 0

General OpenMP discussion

Reduction clause using * instead of + returns 0

Postby arthur.avramiea » Wed Feb 23, 2011 12:00 pm

Hello,

I'm trying to understand the behaviour of the reduction clause with the following program


Code: Select all
#include<stdio.h>
#include<omp.h>

int main(){
   double v[100];
   int i;
   for(i=0;i<10;i++)v[i]=i+1;
   double sum=0;
#pragma omp parallel for default(none) shared(v)\
   reduction(*:sum)
      for(i=0;i<10;i++) {
         int crt;
         crt=omp_get_thread_num();
         sum=sum+v[i];
         printf("thread %i - number %.1f\n",crt,v[i]);
      }
   printf("The result is: %f\n",sum);
}


I know i should have used reduction(+:sum) instead. I wanted to know if reduction(*:sum) computed the product of the local sums for each thread ... which does not happen - the result is 0.
Why is this happening?
arthur.avramiea
 
Posts: 6
Joined: Wed Feb 23, 2011 11:43 am

Re: Reduction clause using * instead of + returns 0

Postby ftinetti » Wed Feb 23, 2011 12:11 pm

I would not expect any good thing/result by declaring
Code: Select all
   reduction(*:sum)

and using
Code: Select all
    sum=sum+v[i];

Instead, I would expect at least a warning from the compiler... or in fact an error...
Maybe the spec. defines something about this... please check and let me know.

Questions:
Compiler and compiler options?
Computer hardware and OS?
ftinetti
 
Posts: 582
Joined: Wed Feb 10, 2010 2:44 pm

Re: Reduction clause using * instead of + returns 0

Postby arthur.avramiea » Wed Feb 23, 2011 12:18 pm

No warnings or errors.
I am using gcc on a macbook 5.2, with mac os x 10.6. This is the output of gcc -v:

Code: Select all
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~105/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)
arthur.avramiea
 
Posts: 6
Joined: Wed Feb 23, 2011 11:43 am

Re: Reduction clause using * instead of + returns 0

Postby ejd » Wed Feb 23, 2011 12:29 pm

This is one of the joys of reduction. Reduction can take many forms, so the OpenMP ARB didn't defined exactly what a reduction looks like. Instead, up until the Version 3.0 specification, section 2.9.3.6 reduction clause, showed what a typical reduction looks like. In the newest specification under review (V3.1), they have removed this.

In any case, the answer to your question is that each thread initializes it's private copy of sum to 0 for a "+" reduction and a 1 for "*" reductions. Since you have coded "sum=sum+v[i]", each partial result will be computed in the thread using "+". However, when the partial sums are combined, they will be combined using the reduction operator specified, or a "*". Note however, that this combination starts with the initial value of sum, which in your code is 0. So zero times anything equals zero and the final result will be zero.

While it is fun to play with and understand what it does, I wouldn't recommend that you try doing this. The result will be dependent on how the work is scheduled on the threads and this could be different for each implementation.
ejd
 
Posts: 1025
Joined: Wed Jan 16, 2008 7:21 am

Re: Reduction clause using * instead of + returns 0

Postby arthur.avramiea » Wed Feb 23, 2011 12:36 pm

So it's 1*(initial value of var)*(product of local results of threads) for reduction(*:var)
and 0+(initial value of var)+(sum of local results)?
arthur.avramiea
 
Posts: 6
Joined: Wed Feb 23, 2011 11:43 am

Re: Reduction clause using * instead of + returns 0

Postby ejd » Wed Feb 23, 2011 12:44 pm

For "reduction(+:sum)" it is going to initialize each thread's private "sum" to 0, perform the operation specified by the user for that private "sum" in each thread (in your case sum = sum + v[i]), and at the end add the values up: (initial value of sum) + (thread 0's private sum) + ...

For "reduction(*:sum)", it is going to initialize each threads private "sum" to 1, perform the operation specified by the user for that private "sum" in each thread, and then multiply the values: (initial value of sum) * (thread 0's private sum) * ...
ejd
 
Posts: 1025
Joined: Wed Jan 16, 2008 7:21 am


Return to Using OpenMP

Who is online

Users browsing this forum: Google [Bot] and 9 guests