函数中的"pragma omp parallel for"在另一个并行循环中调用函数时无效

"pragma omp parallel for" in function not effective when function is called within another parallel loop

本文关键字:函数 并行 循环 无效 另一个 调用 for pragma omp parallel      更新时间:2023-10-16

>在一个并行化的"for"循环中,我调用了一个函数,该函数又包含一个昂贵的计算,我想与其余的CPU并行化。然而,我内心的"并行"指令被忽略了。

这适用于图像处理管道。相机有4个探测器,可拍摄例如100张图像。我想为每个探测器计算 100 张输入图像的中位数。因此,我的外部循环为 4 个检测器使用 4 个线程,我想使用剩余的 CPU 来并行化内部循环中的中位数计算。

int main()
{
// OUTER LOOP over various detectors
# pragma omp parallel for
for (int det=0; det<4; ++det) {
// some serial work
calculate_median(det);
}
}
void calculate_median(int det)
{
// some serial work
#pragma omp parallel for num_threads(available_additional_threads)
for (int pixel =0; pixel < numpixels; ++pixel) {
// create a stack of pixels from the 100 input images
// calculate median of stack
}
// more serial work
}

我根据相机具有的探测器数量和用户计算机上的CPU数量来计算额外的可用线程。像这样,运行的线程永远不会比 CPU 多。

我观察到的是内部的"omp 并行"被忽略,即无论"available_additional_threads"的值如何,我都只得到一个线程。 但是,如果我确实将外部循环设置为单个线程,则内部并行化将按预期工作。这真的让我感到困惑。 非常感谢您的任何额外见解!

更新/解决方案: 设置"omp_set_nested(true("启用了内部循环并行化。

您可以使用编译器支持的折叠子句 OpenMP 3.0

#pragma omp parallel for collapse(2)
for (int x = 0; x < x_max; ++x) {
for (int y = 0; y < y_max; ++y) { 
//parallelize this code here
}
//IMPORTANT: no code in here
}

,但是这个接缝在这里不适用,因为你必须做一些串行工作。

我的经验是,嵌套循环的性能比一个并行循环差,后者很好地面板化了。

通常,最好只并行化外部循环。由于您的外部循环只有 4 次迭代,我认为仅将 OMP 用于内部循环是合理的。调度程序可以更好地处理负载不平衡。

请记住性能重构的黄金法则:度量。

我建议你使用英特尔的Vtune Ampifier等工具来衡量你的性能如何,以及嵌套循环是否真的能帮助你。