2

Is there a way to make OpenMP revert the number of threads (for the next time it's used) back to the default after the application has already called omp_set_num_threads() with a specific number?

For example, is there a special code (e.g. 0 or -1) I supply to omp_set_num_threads?

Or should I just try doing something like omp_set_num_threads(omp_get_max_threads())?

I am making the assumption that the default number is whatever the implementation of OpenMP deems as "optimal". But I don't know what, if anything, the default is guaranteed to be or even what it should be. All I know is that I have an application that calls omp_set_num_threads(4) for one specific OpenMP block which I must not edit (for now). But I'd like to prevent that one setting from affecting other OpenMP blocks in my code.

Joe
  • 5,394
  • 3
  • 23
  • 54
  • 2
    Which compiler and version of OpenMP are you using? – 1201ProgramAlarm Jul 10 '19 at 17:09
  • Visual Studio 2019 and whatever version of GCC is most recent on Ubuntu. I do also sadly have to build the code under Visual Studio 2015 but I am willing to try an alternate, windows-specific approach in that case. Going forward I will be able to stick with VS2019 and beyond – Joe Jul 10 '19 at 19:29
  • 1
    The value set by `omp_set_num_threads` will not be used if a `num_threads` clause is present in the construct. Maybe you could use that in code you control? Or change the "one specific OpenMP block" to use it instead of `omp_set_num_threads`? – 1201ProgramAlarm Jul 10 '19 at 20:45
  • Unfortunately the one specific block is using a configurable parameter that the user can change. So I can't write the number into code with num_threads clause – Joe Jul 10 '19 at 21:07

1 Answers1

3

I've had this problem before. (Disclaimer: I work with MSVC, which currently only implements the OpenMP 2.0 standard). To the best of my knowledge, there is nothing in the OpenMP 2.0 standard that allows you to find out this default value. omp_get_max_threads() is not required to return it (all subsequent emphasis mine):

The omp_get_max_threads function returns an integer that is guaranteed to be at least as large as the number of threads that would be used to form a team if a parallel region without a num_threads clause were to be encountered at that point in the code.

In other words, it might return a number that is larger than the currently set (or default) value.

There is no special value for omp_set_num_threads either:

The omp_set_num_threads function sets the default number of threads to use for subsequent parallel regions that do not specify a num_threads clause. [...] The value of the parameter num_threads must be a positive integer.

And if you get it wrong, it's up to the implementation what will happen:

If a parallel region is encountered while dynamic adjustment of the number of threads is disabled, and the number of threads requested for the parallel region exceeds the number that the run-time system can supply, the behavior of the program is implementation-defined. An implementation may, for example, interrupt the execution of the program, or it may serialize the parallel region.

You might find more precise (and less unsettling) information in the documentation of your OpenMP implementation. However, in the case of MSVC, that documentation is just a verbatim copy of the OpenMP 2.0 standard...


Since you are in the business of modifying the number of threads this way, I would like to preemptively caution about the interaction of omp_set_dynamic with omp_get_num_threads within MSVC:
Why does omp_set_dynamic(1) never adjust the number of threads (in Visual C++)?

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
  • I didn't DV, but maybe because versioin 2.0 is ancient? OpenMP is up to version 5.0. – 1201ProgramAlarm Jul 10 '19 at 17:04
  • @1201ProgramAlarm I agree (and will add a disclaimer), but latest MSVC still only implements the 2.0 standard and I have no experience with OpenMP on other compilers. – Max Langhof Jul 10 '19 at 17:06
  • Yes, please do not quote a almost 20-year old spec in the light that there have been six revisions (three major ones). The post also misses the key point that with latest OpenMP the specification of the number of threads can be list-like structure that cannot be queried from the user code all the nesting levels that might be executed at runtime. So, the only way to query the number of threads for the current level is to open a parallel region, ask for the number of threads and return that number. Caveat is that this number might still be wrong as it may change in the light of `omp_set_dynamic` – Michael Klemm Jul 10 '19 at 17:07
  • @MichaelKlemm That 20-year old spec is the latest one supported by one of the three big C++ compilers. I too wish that were different, but as of right now my answer is exactly what I would've been looking for a few months ago and what I assume the asker wants to know if they are using MSVC right now. And even if they're not, it probably will help others (unless MSVC updates their OMP support tomorrow). – Max Langhof Jul 10 '19 at 17:11
  • @MichaelKlemm Thanks for explaining your thoughts though, it helps! – Max Langhof Jul 10 '19 at 17:17
  • Visual Studio 2019 (which I am using) appears to indicate that it supports Open MP 4.0... sorta. It at least talks about SIMD extensions. https://learn.microsoft.com/en-us/cpp/parallel/openmp/openmp-simd?view=vs-2019 – Joe Jul 10 '19 at 19:18
  • Perhaps I should attempt to ask the current computer how many cores I have to work with and use that...? – Joe Jul 10 '19 at 19:18
  • 1
    @Joe [MSVC supports](https://learn.microsoft.com/en-us/cpp/build/reference/openmp-enable-openmp-2-0-support?view=vs-2019) OpenMP 2.0, and enables SIMD functionality with the `/openmp:experimental` optiion. – 1201ProgramAlarm Jul 10 '19 at 20:46