function ex1()
task = @Threads.spawn begin
st = time()
sleep(1.0)
return time() - st
end
st2 = time()
while time() - st2 < 5 end
println("task slept for $(fetch(task)) seconds")
end
When I start Julia 1.7.1 with julia -t2 and run ex1(), the result is “task slept for 5.0 seconds”.
With the following code, the result is “task slept for 1 seconds”:
function ex2()
task = @Threads.spawn begin
st = time()
sleep(1.0)
return time() - st
end
@Threads.spawn begin
st2 = time()
while time() - st2 < 5 end
end
println("task slept for $(fetch(task)) seconds")
end
What is happening here? Why does the task sleep for 5 seconds in the first case?
I understand that @Threads.spawn can spawn the task onto thread 1 (discussed here: https://github.com/JuliaLang/julia/issues/34267). But the delay occurs even if the task is spawned to thread 2. Also, this wouldn’t explain why ex2() never seems to have a delay.
You are right, after restarting Julia the timings are not consistent for me either.
However, why does the 5 second sleep happen at all?
Can I somehow coerce the task scheduling to consistently give me the expected result (the 1 second sleep)?
I don’t really know a lot of under-the-hood details of julia multithreading but my first guess was that it could be the case that your MulitThr. task gets scheduled on the main julia thread (the thread #1), since julia doesn’t treat the main thread in any special way. Hence, I would recommend using ThreadPools.spawnbg just to make sure that the background thread is indeed used. However, after the quick check, it was clear that it wasn’t it.
I bet that the problem is with the sleep function. If you do something like this instead of your original code it works as expected:
function ex1()
task = Threads.@spawn begin
st = time()
while time() - st < 1
end
return time() - st
end
st2 = time()
while time() - st2 < 5
end
return println("task slept for $(fetch(task)) seconds")
end
task slept for 1.0 seconds
task slept for 1.0 seconds
task slept for 1.0 seconds
I think there is some weird interaction with thread #1 (the main julia thread) inside the sleep function, since it was designed for the async tasks (green threads); hence it “blocks”(yields back to the event loop, or whatever it is called in julia) your spawned task and doesn’t continue working until the main thread yields back, which doesn’t happen until it calls fetch (exactly after 5 seconds).
I filed an issue regarding this, so hopefully it is going to be fixed.