Open mratsim opened 2 years ago
As long as this (or some other) limit still exists, it would be nice if TP_MaxWorkers
or some wrapper for it would be public.
(In my case the user selects the number of threads, so being able to tell the user the max allowed value would be preferable to an exception)
After some mulling over, I have found a way to fix that and implemented the fix in Constantine's threadpool.
The limitation comes from the SparseSet
data structure: https://github.com/status-im/nim-taskpools/blob/15e23ef1cf0860330dcc32f50fcce5f840031e28/taskpools/sparsesets.nim#L14-L38
When a threads run out of tasks in its queue, it needs to select other threads to try to steal from. The random sampling of the next victim needs to be fast, hence the data structure needs to be able to guarantee you pick only from unpicked threads (sampling without replacement)
With a naive set, you would need to uncompress it to a sequence of only unvisited threads before randomly picking from it. With a sparseset, there is no need. But sparsesets are quite heavy in terms of memory, 2n, n the number of threads, hence allowing up to 255 (a byte) threads in those to limit memory.
An easy way would be to change from a byte to an uint32, or another way is to find a function that guarantees that over a range [0, N) each number would be visited, and only once. As a bonus we would like this to have a non-trivial random distribution (i.e. not incrementing and decrementing 1) for better load-balance/distributing contention.
There are 2 such functions that are fast and straightforward to implement:
I've implementing the first one in Constantine's threadpool:
which would map to modify randomPick
in nim-taskpools:
https://github.com/status-im/nim-taskpools/blob/15e23ef1cf0860330dcc32f50fcce5f840031e28/taskpools/taskpools.nim#L200-L215
Now the state is only 2 integers, however many threads there are.