(OpenMP) Как запустить каждую функцию 1 раз в 1 поток

У меня есть 4 темы, и я хочу запустить одновременно 3 функции. Каждая функция занимает один поток.
Но этот код запускается каждую функцию 4 раза

#pragma omp parallel
{
Func1();
Func2();
Func3();
}

и у меня есть такой результат:

Func *1* началось

Func *1* началось

Func *1* началось

Func *1* началось

Func *1* закончено

Func *1* закончено

Func *1* закончено

Func *1* закончено

Func *2* началось

Func *2* началось

Func *2* началось

Func *2* началось

Func *2* закончено

Func *2* закончено

Func *2* закончено

Func *2* закончено

Как я должен изменить код для отображения примерно так:

Func *1* началось

Func *2* началось

Func *3* началось

Func *2* закончено

Func *1* закончено

Func *3* закончено

0

Решение

То, что вы ищете, это sections конструктивная конструкция. Синтаксис должен быть следующим:

#pragma omp parallel
{
#pragma omp sections
{
#pragma omp section
Func1();
#pragma omp section
Func2();
#pragma omp section
Func3();
}
}

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

5

Другие решения

Как уже ответил Массимилиано, самый простой способ достичь того, что вы хотите, это использовать sections построить:

#pragma omp parallel sections
{
#pragma omp section
Func1();
#pragma omp section
Func2();
#pragma omp section
Func3();
}

(когда sections конструкция является единственным вложенным в parallel регион, обе прагмы могут быть объединены, как показано)

каждый section определяет оператор или блок, следующий сразу за ним. Например. если вы хотите добавить еще какой-то код в раздел, вы должны поместить его в блок:

#pragma omp section
{
Func1();
SomeOtherFunc1();
}

Более общий способ управления тем, что делает каждый поток, состоит в проверке идентификатора потока, возвращаемого omp_get_thread_num() и разветвляться в соответствии. Это похоже на способ написания MPI-программ:

#pragma omp parallel
{
switch (omp_get_thread_num())
{
case 0:
Func1();
break;
case 1:
Func2();
break;
case 2:
Func3();
break;
default:
// Do nothing
}
}

Один очевидный недостаток состоит в том, что он будет работать только в том случае, если в команде, выполняющей параллельную область, будет хотя бы 3 потока, то есть код, основанный на идентификаторах потоков, станет несколько непереносимым. В отличие от sections директива работает с любым количеством потоков, например если есть только один поток, все разделы будут выполняться последовательно.

1

По вопросам рекламы [email protected]