[gcc,libgomp] Validation for an approach to PR115367
Léo Hardt via Gcc <[email protected]> Sat, 18 Jul 2026 01:03:52 -0300
| Newsgroups | gmane.comp.gcc.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello, everyone. Not sure if this is the appropriate channel to ask, or whether I should just contact the libgomp maintainers directly. GCC interests me a lot and I have been submitting patches for some nits, but not code that would solve a PR yet. I noticed on PR115367 and some adjacent links [1] that the libgomp implementation of OMP_DYNAMIC is not exactly popular, and it is noted that the library code itself remarks a lack of guideline/recommendation for how many threads it should actually spawn. The current approach for Linux is, whenever a parallel block starts, we call glibc getloadavg, take the 15min average, and decide to use "n_cores - load_avg_15min" [2] as the number of threads. Some have argued online that 15min is too long, while some have argued 1min would be too short. It seems these opinions depend on the developers' perception of the "expected task" duration. With that in mind, I would like to suggest (and in the future, implement) three approaches to ease this: 1. Notice that if you have two parallel blocks, one after another, and the first one runs for <1s, asking the 15min average from the kernel again would yield almost the same answer, and the overhead of this call would not have been used well. My suggestion here is to memoize loadavg and the measurement's timestamp. Then, we would only request it again if at least 30s have passed. [3] 2. If we memoize as point 1 above suggests, I would also say that GOMP_parallel_start is not the best place to do so. Every cycle we lose here is a cycle that N threads could be using in their own CPU cores. Perhaps it would be opportunistic to get this info in GOMP_parallel_end, since we are more likely to be waiting for other threads to finish. 3. Given the way that the sysinfo syscall works, if we read the 15min average, we also have the 1min and 5min averages as well, and we could also get the program running time with minimal overhead. Given these four variables, we are tasked to come up with some heuristic to achieve good a performance/resource balance. libgomp's current answer is "n_cores - load_avg_15min". I would suggest: 3.1 If the 1min average is lower than the 15min's, and the program is running for less than 1min (such as most command line tools), we could interpret that the user just finished a heavy workload and that we can use more threads than the 15min avg would suggest. 3.2 If the program has been running for some minutes, instead of using "n_cores - load", we could use "n_cores - load + 1", since the current thread will work as well, and might as well have been counted in the average. Benchmarking these approaches seems fun. Let me know what you think, or if there is already work being done on this PR. Best regards, Léo [1] - https://github.com/opencv/opencv/issues/25717 - https://github.com/numba/numba/issues/10454 - https://stackoverflow.com/questions/78584145/why-does-my-openmp-app-sometimes-use-only-1-thread-sometimes-3-sometimes-all-c/78584146 [2] Not quite the number of cores, but illustrative enough for an e-mail. [3] If your program has very small tasks, the overhead of many "getloadavg" calls might be noticeable. In my computer, it seems to take north of a microsecond, although the test was very barebones.