OpenMP для цикла игнорирует предложение num_threads - PullRequest
0 голосов
/ 04 февраля 2011

У меня есть следующий код в VS2008:

int i,j;
bool pr = false;
#pragma omp parallel for private(pr) num_threads(2)
for(i=0;i<PIC_X;i++)
{
    int rank = omp_get_thread_num();
    int count = omp_get_num_threads();
    if ( !pr )
    {
        printf_s("Hello from thread %d of %d\n", rank, count);
        pr = true;
    }
    for(j=0;j<PIC_Y;j++)
    {
        // do stuff
    }
}

(не пытаясь сделать вложенный цикл OpenMP, если вам интересно).Проблема в том, что предложение num_threads не имеет никакого эффекта: я всегда получаю «Hello from thread 0 of 1» на выходе.Я пытался использовать omp_set_num_threads(2), но безрезультатно.Что дает?

Ответы [ 2 ]

4 голосов
/ 04 февраля 2011

Вы установили pr вне параллельной области, а затем сделали pr private, поместив его в предложение private.Это означает, что у каждого потока есть pr, но приватные переменные pr не инициализируются.Используйте firstprivate, а не private для pr, чтобы инициализировать закрытые переменные.

Однако вы ошибаетесь, считая счетчики циклов частными по умолчанию.Счетчик циклов для совместного использования (или канонического) для (т. Е. Переменной i) является частным (раздел 2.4.1 для Construct спецификации OMP V2.0).Но "J" нет.См. Спецификацию OpenMP V2.0 (которую Microsoft поддерживает в VS2008), раздел 2.7.2. Атрибуты общего доступа к данным:

Если переменная видима, когда параллельная или рабочая структуравстречается, и переменная не указана в предложении атрибута общего доступа или директиве threadprivate, тогда переменная является общей.Статические переменные, объявленные в динамическом экстенте параллельной области, являются общими.Распределенная память кучи (например, с помощью malloc () в C или C ++ или оператора new в C ++) используется совместно.(Однако указатель на эту память может быть как личным, так и общим.) Переменные с автоматической продолжительностью хранения, объявленной в динамическом экстенте параллельного региона, являются личными.

Что касается omp_get_num_threads (), возвращающего1, я могу думать только о том, что вы не скомпилировали это с включенным флагом OpenMP.

1 голос
/ 04 февраля 2011

Если OpenMP разбивает внешний цикл на 2 (то есть один процесс получает 0..PIC_X / 2), а другой получает последнюю половину, только один процесс увидит i == 0.

И если ваше изображение организовано, как все изображения, которые я видел, внешний цикл должен быть Y, а внутренний цикл должен быть X, а внутренний цикл должен быть OpenMP, потому что именно так изображения обычно организованы в памяти.

...