从代码覆盖OMP_NUM_THREADS-实际

时间:2019-05-29 13:00:14

标签: c++ multithreading openmp

到目前为止,我能找到的所有答案都建议致电omp_set_num_threads。尽管在大多数情况下这是一个正确的答案,但对我而言不起作用。在内部,调用omp_set_num_threads会创建每个线程的ICV(或修改,如果当前线程已经有一个),并且线程数存储在该位置。这意味着,如果有一个不同的线程启动了并行区域,那么它将看不到我们的新值。因此,调用omp_set_num_threads!=设置OMP_NUM_THREADS环境变量。

有没有办法改变全球ICV?

旁注-我为什么要这么做:我正在使用一个库,因此为我生成了一个工作线程,所以我实际上无法控制它的生命周期。

最简单的复制示例:

export OMP_NUM_THREADS=3

#include <omp.h>
#include <iostream>
#include <thread>

void job() {
  #pragma omp parallel
  {
    if (omp_get_thread_num() == 0) {
      std::cout << "Num threads:" << omp_get_num_threads() << std::endl;
    }
  };
}


int main () {
  omp_set_num_threads(2);
  #pragma omp parallel
  {
    if (omp_get_thread_num() == 0) {
      std::cout << "Num threads:" << omp_get_num_threads() << std::endl;
    }
  };
  std::thread t(job);
  t.join();
}

这产生

Num threads:2
Num threads:3

2 个答案:

答案 0 :(得分:1)

您要解决的问题超出了OpenMP的规范。 OpenMP假定它是应用程序过程中唯一的编程模型,因此它对创建新线程也执行OpenMP代码时会发生的事情一无所知。

具体来说,对于您的问题:ICV num-threads是线程专用的ICV,这意味着对omp_set_num_threads()的调用只会影响存储在调用omp_set_num_threads()的线程中的ICV

因此,新的std::thread将收到从envionment变量初始化的新副本。您将无法从产生新线程的主线程中进行更改。

答案 1 :(得分:0)

  

从代码中覆盖OMP_NUM_THREADS ...

更改此:

int main () {
  omp_set_num_threads(2);
  #pragma omp parallel
  {
    if (omp_get_thread_num() == 0) {
      std::cout << "Num threads:" << omp_get_num_threads() << std::endl;
    }
  };
  std::thread t(job);
  t.join();
}

对此:

int main () {
  #pragma omp parallel num_threads(2)
  {
    if (omp_get_thread_num() == 0) {
      std::cout << "Num threads:" << omp_get_num_threads() << std::endl;
    }
  };
  std::thread t(job);
  t.join();
}

我相信它可以与Microsoft编译器一起使用,后者在2003年左右都被OpenMP所困扰。如果我没记错的话,OpenMP的2003年版本大约是2.0或2.1版。

另请参阅Difference between num_threads vs. omp_set_num_threads vs OMP_NUM_THREADS