【问题标题】:OpenMP thread managing in for loops在 for 循环中管理 OpenMP 线程
【发布时间】:2020-06-12 14:47:39
【问题描述】:

我正在尝试使用 OpenMP 优化复杂 for 循环中线程的使用。基本代码如下所示:

for (...) //loop1
{
  #pragma omp parallel
  {
    #pragma omp single
    {
      //section that needs to be executed only once
    }

    #pragma omp for
    {
      for (...) //loop2
      {
        ...
      }
    }

    #pragma omp single
    {
      //section that needs to be executed only once
    }

    #pragma omp for
    {
      for (...) //loop3
      {
        ...
      }
    }
    ...
  }
}

我的问题是关于线程的创建/销毁,因为这段代码意味着每次迭代都会创建和销毁 N 个线程。有没有办法告诉运行时重用相同的线程(类似于线程池),或者这是留给实现的东西?

我需要注意这些限制:

  • loop1 的内容可以(并且需要)并发,因为它包含一些相当繁重的科学计算
  • loop1 的迭代必须是有序的,所以循环本身不能并行

编辑 loop1 的每次迭代只能执行一次(所以我不能让整个循环并行

【问题讨论】:

标签: c multithreading optimization concurrency openmp


【解决方案1】:

首先,不会在每个 loop1 迭代中创建/销毁线程。通常有一个线程等待策略,您可以使用OMP_WAITY_POLICY 环境变量来控制它:

https://www.openmp.org/spec-html/5.0/openmpse55.html#x294-20640006.7

此外,没有什么(至少在您的伪代码中)阻止将所有代码包装在一个并行区域中。代码完全可以是:

#pragma omp parallel
for (...) //loop1
{
  #pragma omp single
  {
    //section that needs to be executed only once
  }

  #pragma omp for
  for (...) //loop2
  {
    ...
  }

  #pragma omp single
  {
    //section that needs to be executed only once
  }

  #pragma omp for
  for (...) //loop3
  {
    ...
  }
  ...
}

在每个工作共享结构(即第一单、loop2、第二单和loope)末尾的隐式障碍将保证迭代之间的顺序。在不需要这些障碍的情况下,您可以使用nowait 子句来避免它们。

【讨论】:

  • 规范中没有任何内容说明线程不会在每次 loop1 迭代中创建/销毁(恰恰相反)。因此,运行时理论上可以定期创建线程,尽管 GCC 的 libGOMP 和 Clang/ICC 的 libOMP 在实践中并没有。
  • 还要注意,线程静态变量的保存规则意味着任意创建和销毁线程可能很困难......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多