Search code examples
copenmpc89

Counting does not work properly in OpenMP


I have the function

void collatz(int startNumber, int endNumber, int* iter, int nThreads)
{
    int i, n, counter;
    int isodd; /* 1 if n is odd, 0 if even */
    #pragma omp parallel for
    for (i = startNumber; i <= endNumber; i++)
    {
        counter = 0;
        n = i;
        omp_set_num_threads(nThreads);
        while (n > 1)
        {
            isodd = n%2;
            if (isodd)
                n = 3*n+1;
            else
                n/=2;
            counter++;
        }
        iter[i - startNumber] = counter;
    }
}

It works as I wish when running serial (i.e. compiling without OpenMP or commenting out #pragma omp parallel for and omp_set_num_threads(nThreads);). However, the parallel version produces the wrong result and I think it is because the counter variable need to be set to zero at the beginning of each for loop and perhaps another thread can work with the non-zeroed counter value. But even if I use #pragma omp parallel for private(counter), the problem still occurs. What am I missing?

I compile the program as C89.


Solution

  • Inside your OpenMP parallel region, you are assigning values to the counter, n and isodd scalar variables. These cannot therefore be just shared as they are by default. You need to pay extra attention to them.

    A quick analysis shows that as their values is only meaningful inside the parallel region and only for the current thread, so it becomes clear that they need to be declared private.

    Adding a private( counter, n, isodd ) clause to your #pragma omp parallel directive should fix the issue.