使用OpenMP并行化内部循环

6
我有三个嵌套循环,但只有最内层可以并行化。外层和中间层的停止条件取决于最内层循环所执行的计算,因此我不能改变它们的顺序。
我在最内层循环之前使用了OPENMP pragma指令,但是使用两个线程的性能比一个线程还差。我猜这是因为线程被创建在外部循环的每次迭代中。
有没有办法在外层循环之外创建线程,但只在最内层循环中使用它呢?
提前感谢。

2
请展示给我们代码,或者更好的是,一个简化的例子来展示问题。 - user180326
2个回答

5

OpenMP应该使用线程池,这样每次执行循环时就不需要重新创建线程。严格来说,这可能取决于您使用的OpenMP实现(我知道GNU编译器使用线程池)。我建议您寻找其他常见问题,例如虚假共享。


谢谢大家的评论。我会再次检查我的代码。有人可以推荐一个适用于多线程代码的好用的免费分析器/代码分析工具吗? - Hernan

4

很遗憾,当前的多核计算机系统并不适用于这种细粒度内部循环并行处理。这并不是线程创建/分叉问题导致的。正如Itjax指出的那样,几乎所有的OpenMP实现都利用线程池,即它们预先创建了一些线程,并将线程停放在那里。因此,实际上不存在创建线程的开销。

然而,这种内部循环并行化的问题有以下两个开销:

  • 将工作/任务分派给线程:即使我们不需要物理创建线程,至少我们必须将工作(=创建逻辑任务)分配给线程,这通常需要同步。
  • 加入线程:在一个团队中所有的线程之后,这些线程应该被加入(除非使用nowait OpenMP指令)。这通常被实现为屏障操作,也是非常密集的同步。

因此,应该尽量减少实际的线程分配/加入数量。您可以通过增加每次调用内部循环的工作量来减少这样的开销。这可以通过一些代码更改比如循环展开来完成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接