Search code examples
c++multidimensional-arrayparallel-processingsumopenmp

How to calculate the sum of an array in parallel using C++ and OpenMP?


my task is to parallelize the creation, doubling, and summation of the array seen in my code below using C++ and OpenMP. However, I cannot get the summation to work in parallel properly. This is my first time using OpenMP, and I am also quite new to C++ as well. I have tried what can be seen in my code below as well as other variations (having the sum outside of the for loop, defining a sum in parallel to add to the global sum, I have tried what is suggested here, etc). The sum should be 4.15362e-14, but when I use multiple threads, I get different results each time that are incorrect. What is the proper way to achieve this?

P.S. We have only been taught the critical, master, barrier, and single constructs thus far so I would appreciate if answers would not include any others. Thanks!

#include <iostream>
#include <cmath>
#include <omp.h>

using namespace std;

int main()
{
    const int size = 256;
    double* sinTable = new double[256];
    double sum = 0.0;

    // parallelized
    #pragma omp parallel
    {
        for (int n = 0; n < size; n++)
        {
            sinTable[n] = std::sin(2 * M_PI * n / size);  // calculate and insert element into array  
            sinTable[n] = sinTable[n] * 2;  // double current element in array
            #pragma omp critical
            sum += sinTable[n];  // add element to total sum (one thread at a time)
        }
    }
    // print sum and exit
    cout << "Sum: " << sum << endl;
    return 0;
}

Solution

  • Unfortunately your code is not OK, because you run the for loop number of thread times instead of distributing the work. You should use:

    #pragma omp parallel for

    to distribute the work among threads. Another alternative is to use reduction:

    int main()
    {
        const int size = 256;
        const double step = (2.0 * M_PI) / static_cast<double>(size); 
        double* sinTable = new double[size];
        double sum = 0.0;
    
        // parallelized
        #pragma omp parallel for reduction(+:sum)    
        for (int n = 0; n < size; n++)
        {
            sinTable[n] = std::sin( static_cast<double>(n) * step);   // calculate and insert element into array  
            sinTable[n] = sinTable[n] * 2.0;  // double current element in array
            sum += sinTable[n];  // add element to total sum (one thread at a time)
        }
        
        // print sum and exit
        cout << "Sum: " << sum << endl;
        delete[] sinTable;
        return 0;
    }
    

    Note that in theory the sum should be zero. The value you obtain depends on the order of additions, so slight difference can be observed due to rounding errors.

    size=256  sum(openmp)=2.84217e-14 sum(no openmp)= 4.15362e-14
    size=512  sum(openmp)=5.68434e-14 sum(no openmp)= 5.68434e-14
    size=1024 sum(openmp)=0           sum(no openmp)=-2.83332e-14
    

    Here is the link to CodeExplorer.