Can I use OpenMP reduction when the variable is an array element?

3k views Asked by At

The OpenMP manual says

A type name in a declare reduction directive cannot be a function type, an array type, a reference type, or a type qualified with const, volatile or restrict.

What can I do to produce my results into array elements? I started with:

int main()
{
    // create an input array
    static const int snum = 5000;
    int input[snum];
    for(int i=0; i<snum; ++i){
        input[i] = i+1;
    }

    // shared output variables for reduction
    int sum[2];
    sum[0] = 0;
    sum[1] = 0;

#pragma omp parallel for
#pragma omp declare reduction(+:sum[0])
#pragma omp declare reduction(+:sum[1])
    for(int i=0; i<snum; ++i) {
            int* p = input+i;
            if(i%2==0)
                sum[0] += *p;
            else
                sum[1] += *p;
        }
}

This gives a compiler error:

27013152.cpp:16:9: error: ‘#pragma’ is not allowed here
 #pragma omp declare reduction(+:sum[0])
         ^~~
27013152.cpp:17:33: error: ‘sum’ does not name a type
 #pragma omp declare reduction(+:sum[1])
                                 ^~~
27013152.cpp:17:36: error: expected ‘:’ before ‘[’ token
 #pragma omp declare reduction(+:sum[1])
                                    ^
2

There are 2 answers

0
mattst88 On BEST ANSWER

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;
}
0
Hugo Raguet On

Reduction on arrays in C/C++ is now possible since OpenMP 4.5. Basically, you must specify array sections (see Section 2.4, p. 44 of OpenMP 4.5 spec.). Your #pragma specification would look like this:

#pragma omp parallel reduction(+:sum[:2])

Be careful with this however, you have to realize that each thread will allocate its own version of the array section; if you do this on large arrays with many threads, you will make your memory needs explode.