首页 > 解决方案 > 从代码中覆盖 OMP_NUM_THREADS - 真的

问题描述

到目前为止,我能找到的所有答案都建议致电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

标签: c++multithreadingopenmp

解决方案


您试图实现的问题超出了 OpenMP 的规范。OpenMP 假定它是应用程序进程中唯一的编程模型,因此它确实知道当您创建一个也执行 OpenMP 代码的新线程时会发生什么。

具体来说,对于您的问题:ICVnum-threads是线程私有的 ICV,这意味着对 的调用omp_set_num_threads()仅影响存储在调用omp_set_num_threads().

因此,新的std::thread将收到一个从环境变量初始化的新副本。您将无法从产生新线程的主线程中更改它。


推荐阅读