OpenMP 是不是将已完成部分的重用线程用于另一个部分?

Posted

技术标签:

【中文标题】OpenMP 是不是将已完成部分的重用线程用于另一个部分?【英文标题】:Does OpenMP use reuse threads of completed section for another one?OpenMP 是否将已完成部分的重用线程用于另一个部分? 【发布时间】:2019-04-03 23:48:17 【问题描述】:

假设我已经安装了 OpenMP 来运行多个部分,如下所示:

#pragma omp parallel sections

  #pragma omp section
   func a 
  #pragma omp section
   func b 

现在假设 func b 先完成,而 func a 仍在运行。 OpenMP 是否使用 func a 中使用的线程来进一步并行化 func b?如果没有,有没有办法做到这一点?

编辑: 在之前的问题中建议之前使用的线程保持空闲。有没有办法让他们在仍在运行的部分工作?

【问题讨论】:

How does OpenMP reuse threads的可能重复 我已经看过了。答案说线程保持空闲。我的问题是是否有办法将它们用于仍在运行的部分。 @StaticCrazee OpenMP 应该如何利用 a 部分的线程?上次我检查规范时,每个部分最多应该有一个线程!我能想出的重用线程的唯一方法是在部分上需要一个 nowait 子句(+ 更广泛的并行块)...... 除非您在函数ab 中有一些嵌套并行性,并且已启用嵌套并行性,否则每个部分都由单个​​线程执行。空闲线程不会“帮助并行化”,因为部分是串行代码。 【参考方案1】:

OpenMP 不使用空闲线程来进一步并行化代码中的另一个 section。如果您想在线程之间实现更好的负载平衡,那么您将不得不使用依赖于 OpenMP 任务的更现代的 OpenMP 编程风格。当线程空闲时,空闲线程会自动拾取准备执行的任务。

所以,代码看起来更像这样:

#pragma omp parallel master

  #pragma omp task
   func a   // func a needs to generate more tasks 
  #pragma omp task
   func b   // func b needs to generate more tasks 

【讨论】:

我想补充一下这个答案,两个任务必须单独产生更多子任务才能真正利用负载平衡。 @Zulan:没错。一个典型的比率是任务比线程多 10 倍。这通常为负载平衡提供了足够的工作。另一个阈值取决于每个任务的工作量。该阈值取决于实现,但对于 OpenMP,这通常是大约 100k 个处理器周期。

以上是关于OpenMP 是不是将已完成部分的重用线程用于另一个部分?的主要内容,如果未能解决你的问题,请参考以下文章

Visual C++ 只有一个线程工作 (OpenMP)

混合 C++11 原子和 OpenMP

OpenMP的主要功能,基本构成体都有哪些

用于区域线程关联的 OpenMP 并行

OpenMP 矩阵向量乘法仅在一个线程上执行

如何获得在整个程序执行期间可能创建的最大 OpenMP 线程数?