Reducing on array in OpenMP
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 into S
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 into S
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 section
First method
int A [] = {84, 30, 95, 94, 36, 73, 52, 23, 2, 13};
int S [10] = {0};
#pragma omp parallel
{
int S_private[10] = {0};
#pragma omp for
for (int n=0 ; n<10 ; ++n ) {
for (int m=0; m<=n; ++m){
S_private[n] += A[m];
}
}
#pragma omp critical
{
for(int n=0; n<10; ++n) {
S[n] += S_private[n];
}
}
}
Second method
int A [] = {84, 30, 95, 94, 36, 73, 52, 23, 2, 13};
int S [10] = {0};
int *S_private;
#pragma omp parallel
{
const int nthreads = omp_get_num_threads();
const int ithread = omp_get_thread_num();
#pragma omp single
{
S_private = new int[10*nthreads];
for(int i=0; i<(10*nthreads); i++) S_private[i] = 0;
}
#pragma omp for
for (int n=0 ; n<10 ; ++n )
{
for (int m=0; m<=n; ++m){
S_private[ithread*10+n] += A[m];
}
}
#pragma omp for
for(int i=0; i<10; i++) {
for(int t=0; t<nthreads; t++) {
S[i] += S_private[10*t + i];
}
}
}
delete[] S_private;
Is it possible to do a reduction on an array with openmp?
Only in Fortran in OpenMP 3.0, and probably only with certain compilers.
See the last example (Example 3) on:
http://wikis.sun.com/display/openmp/Fortran+Allocatable+Arrays
OpenMP in C array reduction / parallelize the code
First you have a typo on the name
#pragma omp parallel for reduction (+: reasult[:i])
should actually be "result" not "reasult"
Nonetheless, why are you section the array with result[:i]
? Based on your code, it seems that you wanted to reduce the entire array, namely:
#pragma omp parallel for reduction (+: result)
for (i = 0; i < M; i++)
for(j = 0; j < N; j++)
if ( numbers[j] == i)
result[i]++;
When one's compiler does not support the OpenMP 4.5 array reduction feature one can alternatively explicitly implement the reduction (check this SO thread to see how).
As pointed out by @Hristo Iliev in the comments:
Provided that M * sizeof(result[0]) / #threads is a multiple of the
cache line size, and even if it isn't when the value of M is large
enough, there is absolutely no need to involve reduction in the
process. Unless the program is running on a NUMA system, that is.
Assuming that the aforementioned conditions are met, and if you analyze carefully the outermost loop iterations (i.e., variable i
) are assigned to the threads, and since the variable i
is used to access the result
array, each thread will be updating a different position of the result
array. Therefore, you can simplified your code to:
#pragma omp parallel for
for (i = 0; i < M; i++)
for(j = 0; j < N; j++)
if ( numbers[j] == i)
result[i]++;
OpenMP reduce array without thread-local copies
You could use OpenMPs atomic update
construct, which is already present in OpenMP 3.1:
void myfunc(double* small, double* large, int lLen, // other args) {
#pragma omp parallel for
for (int i=0; i<lLen; i++) {
int sInd = // determined by other args
#pragma omp atomic update
small[sInd] += large[i];
}
}
This should be faster than using locks.
OpenMP: Is array reduction always needed for updating an array in parallel?
You don't need a reduction. It is a feature to avoid copying the same code all over again because they are re-occurring problems (Try to think off, how you would implement a sum-reduction without OpenMP).
What you do right now is working on parallel data (V[i]
) which should not overlap at any iteration (as you state in the question), because you divide by i
itself. Furthermore write to F[...]
shouldn't overlap either, because it only depends on i
and k
OpenMP SIMD reduction in array: error: reduction variable must be shared on entry to this OpenMP pragma
The problem is that GCC 7.3.0 does not support
#pragma omp for simd collapse(4) reduction(+:next[0:width*height])
the use of reduction
of array sections in this context.
This function is support by GCC 9 forwards:
Since GCC 9, there is initial OpenMP 5 support (essentially C/C++,
only). GCC 10 added some more features, mainly for C/C++ but also for
Fortran.
Can I use OpenMP reduction when the variable is an array element?
You're mistaking the error you're getting. It doesn't mean that you can't do the reduction on alternating elements. It means that you can't do the reduction into an element of an array.
That is, you can't do reduction(+:sum[0])
. But you can do the reduction into another scalar variable and then copy into an element of an array afterwards:
void sum_int(const int input[], int num, int *sum)
{
int sum_even = 0, sum_odd = 0;
#pragma omp parallel for reduction(+:sum_even) reduction(+:sum_odd)
for (int i = 0; i < num; i++) {
if (i % 2 == 0)
sum_even += input[i];
else
sum_odd += input[i];
}
sum[0] = sum_even;
sum[1] = sum_odd;
}
Related Topics
How to Get Memory Usage At Runtime Using C++
Are Members of a C++ Struct Initialized to 0 by Default
Is Floating-Point Addition and Multiplication Associative
How to Link Opencv in Qtcreator and Use Qt Library
Why Do We Need a Pure Virtual Destructor in C++
Why Do We Use Volatile Keyword
Why Does C++ Require a User-Provided Default Constructor to Default-Construct a Const Object
Use 'Class' or 'Typename' For Template Parameters
The Written Versions of the Logical Operators
Are Exceptions in C++ Really Slow
How to Call a Base Class'S Virtual Function If I'M Overriding It
Random Number Generation in C++11: How to Generate, How Does It Work
Is It a Conforming Compiler Extension to Treat Non-Constexpr Standard Library Functions as Constexpr
Default Value to a Parameter While Passing by Reference in C++
Difference Between Conversion Specifiers %I and %D in Formatted Io Functions (*Printf/*Scanf)
What Exactly Is a Reentrant Function
Create Registry Entry to Associate File Extension With Application in C++