Ваш код имеет ряд проблем
- Нет такой директивы openMP, как
#pragma omp nowait
, так что вы можете даже не компилировать с включенным OpenMP (так как, когда это так, вы должны получитьсообщение об ошибке, например, см. https://godbolt.org/z/EbYV6h) - Никогда не требуется
#pragma omp barrier
непосредственно перед концом параллельной области (так как главный поток, который будет выполнять следующую последовательную областьне может выйти, пока все потоки также не закончат выполнение в параллельной области.)
Я не понимаю, почему вы хотите использовать вложенный параллелизм. Вы уже выполняете func2 () параллельно, поэтому любое вложение здесь приведет к избыточной подписке.
Вы можете достичь того, что хотите, либо так:
#pragma omp parallel
{
#pragma omp single nowait
func1()
func2();
}
void func2()
{
#pragma omp for schedule(dynamic), nowait
for (...)
... etc ...
}
Или, используя задачии Taskloops, который является потенциально более чистым способом выразить это.
Использование задач, (и, после вашего разъяснения, вы хотите, чтобы function2
выполнялся только один раз (я читал то, что сказал код, поскольку это проще, чемчтение мыслей!)), что-то вроде этого работает
#include <unistd.h>
#include <stdio.h>
#include <omp.h>
void function1()
{
fprintf(stderr,"%d: entering function1\n", omp_get_thread_num());
sleep(1);
fprintf(stderr,"%d: leaving function1\n", omp_get_thread_num());
}
void function2()
{
fprintf(stderr,"%d: entering function2\n", omp_get_thread_num());
#pragma omp taskloop grainsize(1)
for (int i=0; i<10; i++)
{
fprintf(stderr,"%d: starting iteration %d\n",
omp_get_thread_num(),i);
sleep(1);
fprintf(stderr,"%d: finishing iteration %d\n",
omp_get_thread_num(),i);
}
fprintf(stderr,"%d: leaving function2\n", omp_get_thread_num());
}
int main()
{
#pragma omp parallel
{
#pragma omp single
{
fprintf(stderr,"Executing with %d threads\n",
omp_get_num_threads());
#pragma omp task
{
function1();
}
#pragma omp task
{
function2();
}
}
}
}
Вот выполнение на четырех потоках, конечно, возможны другие чередования.
OMP_NUM_THREADS=4 ./a.out
Executing with 4 threads
3: entering function2
2: entering function1
0: starting iteration 0
1: starting iteration 1
3: starting iteration 9
1: finishing iteration 1
3: finishing iteration 9
0: finishing iteration 0
3: starting iteration 8
1: starting iteration 2
2: leaving function1
0: starting iteration 3
2: starting iteration 4
3: finishing iteration 8
1: finishing iteration 2
3: starting iteration 7
0: finishing iteration 3
0: starting iteration 6
2: finishing iteration 4
1: starting iteration 5
0: finishing iteration 6
3: finishing iteration 7
1: finishing iteration 5
3: leaving function2
Вы можете видеть, что только один потоквыполняет каждую из функций [12], и итерации цикла являются общими для всех потоков.