views:

41

answers:

2

Don't understand, where do I get this wrong. If compiled without openmp support, the code works correctly. But with openmp variables seem to get wrong visibility.

I had the following intention. Each thread has its own max_private in which it finds the local maximum. Then a global maximum is found in a critical section.

#include <iostream>
#include <vector>

typedef std::vector<long> Vector;

long max(const Vector& a, const Vector& b)
{
    long max = 0;
    #pragma omp parallel
    {
        long max_private = 0;

        #pragma omp single
        {
            for (   Vector::const_iterator a_it = a.begin();
                    a_it != a.end();
                    ++a_it)
            {
                #pragma omp task
                {
                    for (   Vector::const_iterator b_it = b.begin();
                            b_it != b.end();
                            ++b_it)
                    {
                        if (*a_it + *b_it > max_private) {
                            max_private = *a_it + *b_it;
                        }
                    }
                }
            }
        }

        #pragma omp critical
        {
            std::cout << max_private << std::endl;
            if (max_private > max) {
                max = max_private;
            }
        }
    }
    return max;
}

int main(int argc, char* argv[])
{
    Vector a(100000);
    Vector b(10000);
    for (long i = 0; i < a.size(); ++i) {
        a[i] = i;
    }
    for (long i = 0; i < b.size(); ++i) {
        b[i] = i * i;
    }

    std::cout << max(a, b) << std::endl;

    return 0;
}

I don't want to use parallel for, because latter I'm going to use data structures that don't support random access iterators.

I used g++-4.4 compiler.

A: 

I think what you need is some attributes on the variables. By default all variables are shared, and as you want max_private to be per-thread, you can happily add 'private' clause to its declaration (it might go a bit faster then).

For max, you need to put it inside the omp block, and mark it with 'shared' if it still doesn't work properly (though it should be ok as you have it)

So, I think you want #pragma omp parallel private(max_private) and put both variables outside the main omp block.

gbjbaanb
I have tried your suggestion from the third paragraph, but it doesn't work for me. Here is the diff to make sure, that I understood you right:9c9,10< #pragma omp parallel---> long max_private = 0;> #pragma omp parallel private(max_private)11,12c12< long max_private = 0;<---> max_private = 0;
tswr
It looks like the max_private from the task never copies back to max_private which is local for each thread
tswr
hmm. Not sure - but I'd try adding 'private(max_private)' to the '#pragma omp task' directive.
gbjbaanb
no, that doesn't work either :(
tswr
+1  A: 

Got a detailed answer at the OpenMP forum. http://openmp.org/forum/viewtopic.php?f=3&amp;t=912&amp;start=0

Had to make max_private threadprivate.

tswr