我目前正在使用 OpenMP 进行矩阵计算。我的代码中有几个循环,而不是调用每个循环 #pragma omp parallel for[...] (创建所有线程并立即销毁它们)我想在开始时创建所有线程,并且在程序结束时删除它们以避免开销。 我想要这样的东西:
#pragma omp parallel
{
#pragma omp for[...]
for(...)
#pragma omp for[...]
for(...)
}
问题是我有一些部分只能由一个线程执行,但是在一个循环中,其中包含那些必须并行执行的循环...这就是它的样子:
//have to be execute by only one thread
int a=0,b=0,c=0;
for(a ; a<5 ; a++)
{
//some stuff
//loops which have to be parallelize
#pragma omp parallel for private(b,c) schedule(static) collapse(2)
for (b=0 ; b<8 ; b++);
for(c=0 ; c<10 ; c++)
{
//some other stuff
}
//end of the parallel zone
//stuff to be execute by only one thread
}
(在我的示例中,循环边界非常小。在我的程序中,迭代次数可以达到 20.000...) 我的第一个想法是做这样的事情:
//have to be execute by only one thread
#pragma omp parallel //creating all the threads at the beginning
{
#pragma omp master //or single
{
int a=0,b=0,c=0;
for(a ; a<5 ; a++)
{
//some stuff
//loops which have to be parallelize
#pragma omp for private(b,c) schedule(static) collapse(2)
for (b=0 ; b<8 ; b++);
for(c=0 ; c<10 ; c++)
{
//some other stuff
}
//end of the parallel zone
//stuff to be execute by only one thread
}
}
} //deleting all the threads
它没有编译,我从 gcc 得到这个错误:“工作共享区域可能没有紧密嵌套在工作共享、关键、有序、主任务或显式任务区域中”。
我知道它肯定来自“错误”的嵌套,但我不明白为什么它不起作用。我需要在平行区之前加一道屏障吗?我有点迷茫,不知道如何解决。
预先感谢您的帮助。 干杯。
最佳答案
大多数 OpenMP 运行时不会“创建所有线程并在之后立即销毁它们”。线程在第一个 OpenMP 部分的开头创建,并在程序终止时销毁(至少英特尔的 OpenMP 实现是这样做的)。使用一个大的并行区域而不是几个较小的并行区域没有性能优势。
Intel 的运行时(它是开源的并且可以在 here 中找到)有选项来控制线程用完工作时做什么。默认情况下,它们会旋转一段时间(以防程序立即开始一个新的并行部分),然后它们会让自己进入休眠状态。如果 do sleep,为下一个并行部分启动它们将需要更长的时间,但这取决于区域之间的时间,而不是语法。
关于c - 如何使用 OpenMP 在顺序循环中嵌套并行循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20110429/