Видимость переменных C++ OpenMP в параллельных задачах

Не понимаю, где я ошибаюсь. При компиляции без поддержки openmp код работает корректно. Но с переменными openmp, кажется, получают неправильную видимость.

У меня было следующее намерение. У каждого потока есть свой max_private, в котором он находит локальный максимум. Затем в критической секции находится глобальный максимум.

#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;
}

Я не хочу использовать параллель, потому что в последнем я собираюсь использовать структуры данных, которые не поддерживают итераторы произвольного доступа.

Я использовал компилятор g++-4.4.


person tswr    schedule 20.07.2010    source источник


Ответы (3)


Получил подробный ответ на форуме OpenMP. http://openmp.org/forum/viewtopic.php?f=3&t=912&start=0

Пришлось сделать max_private threadprivate.

person tswr    schedule 21.07.2010

Я думаю, вам нужны некоторые атрибуты переменных. По умолчанию все переменные являются общими, и, поскольку вы хотите, чтобы max_private был для каждого потока, вы можете с радостью добавить предложение «private» в его объявление (тогда это может работать немного быстрее).

Для макса вам нужно поместить его в блок omp и пометить его как «общий», если он все еще не работает должным образом (хотя он должен быть в порядке, поскольку он у вас есть)

Итак, я думаю, вы хотите #pragma omp parallel private(max_private) и поместить обе переменные вне основного блока omp.

person gbjbaanb    schedule 20.07.2010
comment
Я попробовал ваше предложение из третьего абзаца, но оно у меня не работает. Вот разница, чтобы убедиться, что я правильно вас понял: 9c9,10 ‹ #pragma omp parallel --- › long max_private = 0; › #pragma omp parallel private(max_private) 11,12c12 ‹ long max_private = 0; ‹ --- › max_private = 0; - person tswr; 21.07.2010
comment
Похоже, что max_private из задачи никогда не копируется обратно в max_private, который является локальным для каждого потока. - person tswr; 21.07.2010
comment
хм. Не уверен, но я бы попробовал добавить 'private(max_private)' в директиву '#pragma omp task'. - person gbjbaanb; 21.07.2010

Что вам нужно, так это уменьшение openmp, чтобы найти максимум. Он доступен в OpenMP 3.0.

Сделайте сокращение на for

long max(const Vector& a, const Vector& b)
{
    long max_val = 0;  // <- change the name for clarity
    #pragma omp parallel reduction(max : max_val)
    { 
      [...] 
      #pragma omp critical
      {
        std::cout << max_private << std::endl;
        if (max_private > max_val) {
            max_val = max_private;
        }
      }
    }
    return max_val; 
}

max_val является частным в каждом потоке, и в конце цикла происходит сокращение и возвращается максимум каждого потока open_mp.

person ColdCat    schedule 02.08.2013