准备好 openMP theads

计算科学 并行计算 C++
2021-12-20 23:23:35

我有一个 C++ 程序,它有一个双for循环,我想使用 opeMP 进行并行化。它很简单(多项式乘积),长度可变(系数在 100 到 8000 之间),每次执行调用该函数数百万次。

pragma在外部循环周围有平行线,而forpragma 就在 pragma 下方parallel我发现如果元素的数量很大,接近 8000,执行时间很好,低于没有并行化。但是,对于少量的系数,性能会下降,并且并行版本比串行版本慢。

我想这是由于每次调用函数时都会创建/销毁并行线程。我可以在编译指示中限制线程的创建if,所以它只对大多项式进行并行化,但我想知道是否有办法避免线程的创建/销毁,所以我可以创建一次并留下它们“在通话之间等待”,因此他们会在需要时准备好。该函数是我唯一并行化的函数,我无法将并行化移动到调用函数。

我正在使用 g++。

3个回答

英特尔编译器堆栈用于KMP_BLOCKTIME=<time in milliseconds, infinite>设置线程在循环结束(或无限期)后等待进入睡眠的时间。我不知道 GCC 是否支持这个。您可能会尝试设置OMP_WAIT_POLICY=active强制线程始终旋转。这将在循环结束后保持线程运行,但它也可能会影响 OpenMP 调用之间的性能。

一个更复杂的解决方案是将并行区域提升到此例程之上,并将您不想与 single/master 子句并行的代码包装起来。这里的好处是你可能会弄清楚如何增加代码中的线程数量,这对对抗阿姆达尔定律很有好处。另一方面,相对于已经讨论过的解决方案,这样做可能相当复杂,并且没有太多好处。

我想您正在寻找使用 openmp 线程池。我不确定您使用的是哪个 runtme 实现,但通常您可以使用 omp_set_num_threads(int) 在初始化时设置线程池大小。只有在运行时无法创建线程池时,才会在运行时动态创建线程。

但我不确定你如何确定你的瓶颈是线程启动和停止。我建议您分析您的代码以了解您实际遇到瓶颈的位置。