-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
It occurred to me that it might be nice to have @threads f(...) rewrite the function call to something like f(Threads.ThreadsCall{true}(), ...), if only to provide a uniform syntax for requesting a multi-threaded version of an algorithm.
For example, we could write @threads sum(x) to call a sum(::ThreadsCall{true}) method rather than having a sum_threads function. (Of course, in an ideal world with no threading overhead, we could have sum always use a @threads for, but for the foreseeable future this will pay a big price for summing short arrays.)
The reason I suggest ThreadsCall{true} is that this allows you to define functions that share code between the threaded and serial versions:
f(args...) = f(ThreadsCall{false}(), args...) # default is non-threaded
function f(::ThreadsCall{TC}, args...) where {TC}
...some calculations....
if TC
... threaded algorithm ...
else
... serial algorithm ...
end
@maybethreads TC for ... # flag version of @threads for to enable/disable threading
end
... some other calculations ...
return g(ThreadsCall{TC}(), ...) # call subsidiary function and pass TC
endin order to share code between the threaded and non-threaded version, and to pass the choice of whether or not to thread through to subsidiary functions.
As suggested above, it would be nice to also make @maybethreads bool for ... turn into
if bool
@threads for ...
else
for ...
endso that you could write a single loop and use TC from ::ThreadsCall{TC} to decide whether to thread it. Similarly for @maybespawn, @maybesync as suggested below
For #19777, we could write a broadcast(::ThreadsCall{true}, ...) method and then make @threads f.(...) call it.
cc: @jw3126, @baggepinnen, @mohamed82008, who have all written packages with threaded variants of stdlib functions. Eventually it would be nice to fold some of this into base with @threads map(...) etcetera.