OpenMP和嵌套并行性

3

我想使用OpenMP嵌套并行循环。以下是一个示例代码:

#include <iostream>
#include <cmath>

void subproblem(int m) {
  #pragma omp parallel for
  for (int j{0}; j < m; ++j) {
    double sum{0.0};
    for (int k{0}; k < 10000000; ++k) {
      sum += std::cos(static_cast<double>(k));
    }
    #pragma omp critical
    { std::cout << "Sum: " << sum << std::endl; }
  }
}

int main(int argc, const char *argv[]) {
  int n{2};
  int m{8};

  #pragma omp parallel for
  for (int i{0}; i < n; ++i) {
    subproblem(m);
  }

  return 0;
}

以下是我的要求:

  • 如果n>=(我的计算机上的处理器数量),我只希望并行化第一个循环。
  • 如果n<(我的计算机上的处理器数量),我希望OpenMP在内部循环中启动线程,但不希望总线程数超过我的计算机上的处理器数量。

到目前为止,我只找到了一个禁用嵌套并行性或始终允许它的解决方案,但我正在寻找一种方式,只有在启动的线程数低于处理器数量时才启用它。

使用任务的OpenMP是否有这样的解决方案呢?

4个回答

5

与其使用一对嵌套的并行部分,您可以告诉OpenMP将嵌套循环“折叠”为一个在n*m迭代空间上的单个并行部分:

#pragma omp parallel for collapse(2)
for (int i{0}; i < n; ++i) {
  for (int j{0}; j < m; ++j) {
    // ...
  }
}

这将使其能够适当地分割工作,无论n和m的相对值如何。

谢谢。但我的问题被过度简化了。我已经编辑了原始问题。 - InsideLoop

1

OMP_NUM_THREADS - 指定并行区域中默认使用的线程数。该变量的值应为正整数的逗号分隔列表;指定的值表示对应嵌套级别要使用的线程数。如果未定义,则每个 CPU 使用一个线程。(来源于此处)

omp_get_max_threads - 可用于执行工作的最大线程数(来源于此处)

omp_get_num_threads - 当前团队中的线程数(来源于此处)

但是,据我所知,没有函数可以获取所有正在运行的线程数(这就是您的请求:

我不希望总线程数超过我的机器上的核心数

)

还要看这个问题


这对我没有用。不幸的是,通过使用getenv查询OMP_NUM_THREADS,我改变了环境变量的行为。我通过打开一个并行区域来解决了这个问题(请参见http://stackoverflow.com/a/40234153/646993)。 - boraas

1

parallel结构的if子句难道不是为你完成所有工作吗? 以下是第4.0版OpenMP标准第44页上的说明:

The syntax of the parallel construct is as follows:

#pragma omp parallel [clause[ [, ]clause] ...] new-line structured-block

where clause is one of the following:
  if(scalar-expression)
  num_threads(integer-expression)
  default(shared | none)
  private(list)
  firstprivate(list)
  shared(list)
  copyin(list)
  reduction(redution-identifier:list)
  proc_bind(master | close | spread)

我没有尝试过,但我猜想按照你描述的两个条件使用if语句来判断n是否大于计算机核心数可能会奏效...你愿意试一试并告诉我们吗?

0

taskloop解决了你的问题吗?这个页面的第三个代码块展示了它的使用方法。下面是更新后的代码:

#include <iostream>
#include <cmath>

void subproblem(int m) {
  #pragma omp taskloop
  for (int j{0}; j < m; ++j) {
    double sum{0.0};
    for (int k{0}; k < 10000000; ++k) {
      sum += std::cos(static_cast<double>(k));
    }
    #pragma omp critical
    { std::cout << "Sum: " << sum << std::endl; }
  }
}

int main(int argc, const char *argv[]) {
  int n{2};
  int m{8};

  #pragma omp parallel for
  for (int i{0}; i < n; ++i) {
    subproblem(m);
  }

  return 0;
}

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