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