I am trying to parallelize the following program, but don't know how to reduce on an array. I know it is not possible to do so, but is there an alternative? Thanks. (I added reduction on m which is wrong but would like to have an advice on how to do it.)
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <omp.h>
using namespace std;
int main ()
{
int A [] = {84, 30, 95, 94, 36, 73, 52, 23, 2, 13};
int S [10];
time_t start_time = time(NULL);
#pragma omp parallel for private(m) reduction(+:m)
for (int n=0 ; n<10 ; ++n ){
for (int m=0; m<=n; ++m){
S[n] += A[m];
}
}
time_t end_time = time(NULL);
cout << end_time-start_time;
return 0;
}
I have two remarks concerning Zboson's answer:
1. Method 1 is certainly correct but the reduction loop is actually run serially, because of the #pragma omp critical which is of course necessary as the partial matrices are local to each thread and the corresponding reduction has to be done by the thread owing the matrix.
2. Method 2: The initialization loop can be moved outside the single section and therefore become parallelizable.
The following program implements array reduction using openMP v4.0 user defined reduction facility:
This follows verbatim the complex number reduction example on page 97 of OpenMP 4.0 features.
Although the parallel version works correctly, there probably are performance issues, which I have not investigated:
Said "performance issues" are of my own making and it is completely straightforward not to introduce them:
The modified part of the code then is:
Yes it is possible to do an array reduction with OpenMP. In Fortran it even has construct for this. In C/C++ you have to do it yourself. Here are two ways to do it.
The first method makes private version of
S
for each thread, fill them in parallel, and then merges them intoS
in a critical section (see the code below). The second method makes an array with dimentions 10*nthreads. Fills this array in parallel and then merges it intoS
without using a critical section. The second method is much more complicated and can have cache issues especially on multi-socket systems if you are not careful. For more details see this Fill histograms (array reduction) in parallel with OpenMP without using a critical sectionFirst method
Second method
If translating your code to Fortran, which can use arrays in OpenMP reduction operations, doesn't appeal, you could use a bunch of temporary variables. For example
This leaves you with the unappealing prospect of having to write some kind of
if
orcase
statement to determine which of the temporaries is to be updated. If your code is just an example you want to use for learning, carry on.But if your intention is genuinely to write a parallel prefix sum routine then search around. This is a good place to start.