Multi-threading appears to be single thread when some threads cost much more time than the others?

The task structure of @threads :dynamic and @threads :static is actually the same, i.e. both create O(nthreads()) tasks corresponding to contiguous regions of the given (potentially large) iteration range. The only difference is that tasks can migrate (“are non-sticky”) in the former case while they can’t in the latter. Compare this to @sync for ... @spawn ... which create one task per loop iteration and gives a form of load-balancing through Julias task scheduler. In pictures:

Note that neither :static nor :dynamic gives load balancing (as @spawn does). Also note that the task->thread mapping isn’t fixed for :dynamic but is for :static. However, when we sort by workload we see that eventually they do the same thing. So, to summarize, which Julia thread does which chunk is dynamically decided of :dynamic but the chunks are the same as for :static.

(Pluto notebook: load_balancing.jl (45.8 KB) - Be aware though that I use hacky/unsafe threadid() pattern here for simplicity.)

You might want to check out these comments by @tkf:

and the comments in these PRs:

4 Likes