-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix enq_work
behavior when single-threaded
#48702
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is quite right either. I think the issue is that where we set tid = Threads.threadid()
, it should first check if t
has a preferred thread pool instead, instead of pinning it to the current thread.
A similar change will be needed in the other enq_work-like functions (e.g. wait2)
My understanding of the logic is as follows. If Otherwise, if If |
maxthreadid is dynamic, so should not be used for static scheduling decisions is the main challenge |
This particular case is not a static scheduling decision though? If Currently, the only way to create a task on a different thread pool is with |
Is the issue that the threadpool size cannot be determined for the interactive thread pool if this pool does not exist? If an interactive threadpool is not available, what should happen when spawning a task on it? Should this error or simply revert to the default pool? |
base/task.jl
Outdated
@@ -767,7 +767,7 @@ end | |||
|
|||
function enq_work(t::Task) | |||
(t._state === task_state_runnable && t.queue === nothing) || error("schedule: Task not runnable") | |||
if t.sticky || Threads.threadpoolsize() == 1 | |||
if t.sticky || Threads.maxthreadid() == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if t.sticky || Threads.maxthreadid() == 1 | |
if !t.sticky | |
tpid = max(threadpoolid(t), 1) | |
if tpid == 1 && Threads.threadpoolsize(tpid) == 1 | |
ccall(:jl_set_task_tid, Cint, (Any, Cint), t, 1) | |
t.sticky = true | |
end | |
end | |
if t.sticky |
I think this was trying to check specifically the size of the first threadpool, and check if t
is meant to run in the first threadpool, and if both are 1, then to add it to the sticky queue for the first threadpool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reworked this to check for the size of the task's preferred thread pool, whichever it is.
Allow specifying which thread pool's size to retrieve.
Now returns `threadpoolsize(pool)`.
If a task is spawned with `:interactive` but there are no interactive threads, set the task's thread pool to `:default` so that we don't have to keep checking it in other places.
enq_work
behavior when single-threaded
Sorry, forgot to answer this. The recent commits should make it clearer, but basically if there's only one thread in whichever thread pool a task is to run in, we want to behave as though that task is sticky (i.e. use the thread's work queue rather than the multiqueue) as a small optimization. Your other question should also be answered by one of the commits here -- if there is no interactive thread pool, we simply revert to the default thread pool. |
If there's only one thread in the task's preferred thread pool, use that thread's work queue.
Is this done then @vtjnash? |
If there's only one thread in the task's preferred thread pool, use that thread's work queue.
Fixes #48644.
Fixes #47756