Repository: opencv
Issue: Use of omp_set_dynamic() creates nonsensical OpenMP behaviour, using only 1 thread
Labels: bug

### System Information

All Linux systems, probably more, see `libomp` code.

### Detailed description

@alalek I think the behaviour introduced in

* https://github.com/opencv/opencv/pull/12796

is bad because of how [`OMP_DYNAMIC`] is implemented. It makes that OpenMP does not use all available cores.

I noticed that when starting my C++ app, only 1 thread is used, even though the system is idle.

* On other machines with the same spec, running the same binary, all cores were used.
* Running the app a few minutes later made a couple more threads used.
* The more I waited, the more performant the app got.

Setting e.g. `OMP_NUM_THREADS=100` did not help.

I took a wild guess and observed the observed parallelism against the 15-minute load average of the machine:

```
15 min load average
    2.55 -> 10 threads
    4.64 -> 8 threads
    4.93 -> 7 threads
```

My program's code path in question doesn't even use, but only link/load OpenCV.

I eventually found the implementation: [`libgomp/config/linux/proc.c`](https://github.com/gcc-mirror/gcc/blob/10cb3336ba1ac89b258f627222e668b023a6d3d4/libgomp/config/linux/proc.c#L180-L188)

```c
/* When OMP_DYNAMIC is set, at thread launch determine the number of
   threads we should spawn for this team.  */
/* ??? I have no idea what best practice for this is.  Surely some
   function of the number of processors that are *still* online and
   the load average.  Here I use the number of processors online
   minus the 15 minute load average.  */

unsigned
gomp_dynamic_max_threads (void) {
///
    return n_onln - loadavg;
```

## This is really bad

* Because of this logic, your app will use only 1 thread, even though the system is completely idle _now_, just because it was busy 10 minutes ago.
* The dynamic limit is determined _at process start_ (loading time), and fixed forever.
  * So started programs stay slow _forever_ if they were started at a time 5 minutes after the system was busy.
* It means a server can never achieve full utilisation when working down a queue of jobs.
  * Say you have 8 cores, and a queue of N jobs to process, each of which takes 15 minutes full-CPU.
  * The first jobs starts at 0 15-min-utilisation, thus using all cores.
  * The next job starts, using only 1 core.
  * The next job starts, using only 7 cores.
  * The next job starts, using only 1 cores.
  * The next job starts, using only 7 cores.
  * ...
  * In the long run, the **server uses only half of its cores on average**.
* It makes performance behaviour completely irreproducible.
* This should not be on by default.

OpenCV isn't really to blame here, because the [docs of `OMP_DYNAMIC`](https://gcc.gnu.org/onlinedocs/libgomp/OMP_005fDYNAMIC.html) point none of this out. You have to read the implementation to learn it.

## Solution

I petition OpenCV to disable this logic by default, setting `OPENCV_FOR_OPENMP_DYNAMIC_DISABLE=1` by default.

### Steps to reproduce

```sh
stress-ng --cpu 0
# wait 15 minutes, then Ctrl+C

# Now run your app that links OpenCV. 
# It will use only 1 thread for the next 10 minutes.
```

### Issue submission checklist

- [X] I report the issue, it's not a question
- [X] I checked the problem with documentation, FAQ, open issues, forum.opencv.org, Stack Overflow, etc and have not found any solution
- [X] I updated to the latest OpenCV version and the issue is still there
- [X] There is reproducer code and related data files (videos, images, onnx, etc)