omp parallel vs. omp parallel для

105

В чем разница между этими двумя?

[A]

#pragma omp parallel
{ 
    #pragma omp for
    for(int i = 1; i < 100; ++i)
    {
        ...
    }
}

[B]

#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
   ...
}
Хюнджик Бэ
источник

Ответы:

65

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

Комбинированные конструкции параллельной совместной работы - это ярлык для указания параллельной конструкции, содержащей одну конструкцию совместной работы и никаких других операторов. Разрешенные пункты - это совокупность пунктов, разрешенных для параллельных договоров и договоров о совместной работе.

Взято с http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

Спецификации OpenMP находятся здесь:

https://openmp.org/specifications/

Аде Миллер
источник
66

Они эквивалентны.

#pragma omp parallelпорождает группу потоков, #pragma omp forразделяя итерации цикла между порожденными потоками. С помощью #pragma omp parallel forдирективы fused вы можете делать обе вещи одновременно .

Кшиштоф Косиньски
источник
В своем коде я использую именно эту структуру. Однако, когда я использую schedule(static, chunk)предложение в директиве, у меня возникает проблема. Код работает нормально, но когда я вызываю этот код из программы MPI, он заходит в бесконечный цикл. Счетчик цикла равен нулю на всех итерациях этого цикла. У меня счетчик циклов определен как частный в #pragma omp parallelдирективе. Понятия не имею, почему это не удается только тогда, когда MPI вызывает код. Я в некоторой степени уверен, что каждый процесс MPI выполняется на другом процессоре кластера, если это имеет значение. Понятия не имею, является ли расписание причиной проблемы.
Рохит Банга
То же самое отлично работает, когда я использую #pragma omp parallel forдирективу. Должна быть какая-то разница.
Рохит Банга
1
Обновление: как оказалось, я наблюдаю эту проблему только тогда, когда использую предложение расписания, поэтому я предполагаю, что это не зависит от того, использую ли я комбинированную параллель для или двух разных директив.
Рохит Банга
28

Вот пример использования разделенных parallelи for здесь . Вкратце, его можно использовать для динамического выделения частных массивов потоков OpenMP перед выполнением forцикла в нескольких потоках. В parallel forслучае, если такую ​​же инициализацию сделать невозможно .

UPD: В примере вопроса нет разницы между одной прагмой и двумя прагмами. Но на практике вы можете сделать более ориентированное на поток поведение с разделенными директивами parallel и for. Какой-то код, например:

#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}
НцДК
источник
9

Хотя обе версии конкретного примера эквивалентны, как уже упоминалось в других ответах, между ними все же есть одно небольшое различие. Первая версия включает ненужный неявный барьер, встречающийся в конце "omp for". Другой неявный барьер можно найти в конце параллельной области. Добавление nowait к omp for сделало бы два кода эквивалентными, по крайней мере, с точки зрения OpenMP. Я упоминаю об этом, потому что компилятор OpenMP может генерировать немного другой код для этих двух случаев.

пхаджидо
источник
7

Я вижу совершенно разные времена выполнения, когда беру цикл for в g ++ 4.7.0 и использую

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;

for (int i = 0; i < 5000000; i++)
{
   double r1 = ((double)rand() / double(RAND_MAX)) * 5;
   double r2 = ((double)rand() / double(RAND_MAX)) * 5;
   x.push_back(r1);
   y.push_back(r2);
}

int sz = x.size();

#pragma omp parallel for

for (int i = 0; i< sz; i++)
   prod[i] = x[i] * y[i];

серийный код (нет openmp) запускается через 79 мс. код "parallel for" выполняется за 29 мс. Если я опущу forи использую #pragma omp parallel, время выполнения увеличится до 179 мс, что медленнее, чем последовательный код. (машина имеет параллелизм 8)

код ссылается на libgomp

parcompute
источник
2
Я думаю, это потому, что omp parallel выполняет цикл в отдельном потоке, не разделяя его на потоки, поэтому основной поток ожидает завершения второго потока. а время тратится на синхронизацию.
Antigluk
7
Это потому, что без a #pragma omp forвообще нет многопоточного разделения цикла. Но в любом случае это был не случай OP, попробуйте еще раз с дополнительным #pragma omp forвнутри, #pragm omp parallelи он должен работать аналогично (если не так), как #pragma omp parallel forверсия.
Christian Rau
2
Я считаю этот ответ лучшим, поскольку он показывает, что они не "эквивалентны"
Ученый-
6

Очевидно, существует множество ответов, но этот отвечает очень хорошо (с исходным кодом)

#pragma omp forделегирует только части цикла для разных потоков в текущей команде. Команда - это группа потоков, выполняющих программу. При запуске программы команда состоит только из одного участника: главного потока, который запускает программу.

Чтобы создать новую группу потоков, вам нужно указать ключевое слово parallel. Его можно указать в окружающем контексте:

#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}

и:

Что такое: параллельно, для и команды

Разница между parallel, parallel for и for заключается в следующем:

Команда - это группа потоков, которые выполняются в данный момент. В начале программы команда состоит из одного потока. Параллельная конструкция разделяет текущий поток на новую группу потоков на время следующего блока / оператора, после чего группа снова объединяется в одну. for разделяет работу цикла for между потоками текущей команды.

Он не создает потоки, он только разделяет работу между потоками выполняющейся в данный момент команды. parallel for - это сокращение сразу для двух команд: parallel и for. Parallel создает новую команду, и при разделениях эта команда обрабатывает различные части цикла. Если ваша программа никогда не содержит параллельной конструкции, никогда не может быть более одного потока; главный поток, который запускает программу и запускает ее, как в непоточных программах.

https://bisqwit.iki.fi/story/howto/openmp/

туманx
источник