如果堆栈较低的函数已经触发并行计算,则忽略并行计算请求



是否有可能与OpenMP,当一个函数,较低的堆栈,点燃多处理,然后OpenMP设施忽略多处理请求从函数体,较高的堆栈?

这是OpenMP一直工作的方式吗?如果不行,我可以这样做吗?如何?

void do1()
{
#pragma omp parallel for
for (unsigned int i = 0; i < 10; ++i);
}
void do2()
{
#pragma omp parallel for
for (unsigned int i = 0; i < 10; ++i) do1();
}
void do3()
{
#pragma omp parallel for
for (unsigned int i = 0; i < 10; ++i) do2();
}
int main()
{
do1(); // runs in parallel
do2(); // do2() runs in parallel, do1() I want not
do3(); // do3() runs in parallel, do1() and do2() I want not
}

如果禁用嵌套并行性,OpenMP的工作原理与您描述的完全相同。在当前的OpenMP实现中,默认情况下它是禁用的,但标准中没有指定它,因此为了安全起见,值得通过将OMP_MAX_ACTIVE_LEVELS环境变量设置为1或在代码中使用omp_set_max_active_levels(1);函数来禁用它。

这种情况称为嵌套,它通常效率低下(尽管这取决于运行时)。您可以调整OpenMP运行时参数来缓解性能问题(参见@Laci的答案),但老实说,这种模式通常会导致比它解决的更多的问题。现代的解决方案是简单地使用任务更具体地说,是taskloop指令。或者,您可以使用if(...)子句来调整并行段行为(例如:根据给定条件禁用并行性)。任务的调度依赖于运行时。例如,IOMP (Clang/ICC)基于(随机的)工作窃取算法,而GCC使用有界的集中式队列。任务的开销可能大于并行段的开销(特别是在静态调度时)。

注意,堆栈帧可以由编译器优化。事实上,do1do2do3可以内联,这样在运行时就不会留下这些函数的踪迹。

最新更新