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


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/

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.