Reduction Clause

Check the following code:

#include <stdio.h>
#include <omp.h>

int main(void)
{    
    int sum = 100;

    #pragma omp parallel for
    for (int i = 1; i <= 4; i++)
    {
        sum += i;
    }

    printf("sum is %d\n", sum);
    return 0;
}

Because sum is a shared variable in threads, so we need to use synchronization to protect accessing it:

#pragma omp parallel for
for (int i = 1; i <= 4; i++)
{
    #pragma omp critical
    sum += i;
}

But this will cause losing the advantage of using parallelism. The other method is using reduction clause:

reduction(reduction-identifier : list)    

Modify the above code to understand reduction clause better:

#include <stdio.h>
#include <omp.h>

int main(void)
{    
    int sum = 100;

    printf("Before parallelism, sum's address is %p\n", &sum);

    #pragma omp parallel for reduction(+ : sum)
    for (int i = 1; i <= 4; i++)
    {
        printf("sum's address in thread %d is %p, value is %d\n", omp_get_thread_num(), &sum, sum);
        sum += i;
    }

    printf("After parallelism, sum's address is %p, and value is %d\n", &sum, sum);
    return 0;
}  

In above reduction(+ : sum) clause, + is reduction-identifier and sum is list. Build and run it:

# gcc -fopenmp parallel.c
# ./a.out
Before parallelism, sum's address is 0x7ffcc880baf0
sum's address in thread 3 is 0x7f6baea5ee20, value is 0
sum's address in thread 2 is 0x7f6baf25fe20, value is 0
sum's address in thread 0 is 0x7ffcc880ba90, value is 0
sum's address in thread 1 is 0x7f6bafa60e20, value is 0
After parallelism, sum's address is 0x7ffcc880baf0, and value is 110

From the output, we can see every thread gets a local copy of sum (different addresses), but it is initialized to 0 (this is according to the + operation), not an unspecified value. After finishing this parallel region, the local sum of every thread are reduced to one value, and combined to the original shared sum defined in main function (the value is 110).

Besides +, OpenMP also supports other operators, such as -, *, and so on. Based on the reduction-identifier, the initial values of list are also different. E.g., for *, the initial value is 1, not 0.

results matching ""

    No results matching ""