3

All the answers I was able to find so far suggest calling omp_set_num_threads. While it's a proper answer for most cases, it doesn't work for me. Internally, calling omp_set_num_threads causes a creation of per-thread ICV (or modification, if current thread already has one), and the number of threads is stored there. This means that if there is a different thread, that starts a parallel region, it won't see our new value. So calling omp_set_num_threads != setting OMP_NUM_THREADS env variable.

Is there a way to change global ICV?

Side note - why would I want to to this: I'm working with a library spawns a worker thread for me, so I don't really control it's life-cycle.

Simplest example to reproduce:

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();
}

This produces

Num threads:2
Num threads:3
S. Kaczor
  • 401
  • 3
  • 8

2 Answers2

4

The problem with what you're trying to achieve is outside of OpenMP's specification. OpenMP assumes that it's the only programming model in the application process and thus it does know anything about what happens when you create a new thread that also executes OpenMP code.

Specifically, for your problem: the ICV num-threads is a thread-private ICV, that means, that a call to omp_set_num_threads() only affects the ICV stored in the thread that calls omp_set_num_threads().

So, the new std::thread will receive a new copy that initialized from the envionment variable. You won't be able to change it from the master thread that spawned the new thread.

Michael Klemm
  • 2,658
  • 1
  • 12
  • 15
0

Overriding OMP_NUM_THREADS from code...

Change this:

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();
}

to this:

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();
}

I believe that works with Microsoft compilers, which are stuck somewhere around 2003 for OpenMP. The 2003 release of OpenMP is roughly version 2.0 or 2.1, if I recall correctly.

Also see Difference between num_threads vs. omp_set_num_threads vs OMP_NUM_THREADS.

jww
  • 97,681
  • 90
  • 411
  • 885