Assume you have a long-running, “expensive” function, e.g.,
function longrun()
dim = 20000
A = rand(dim,dim)/dim
A^256
end
which may take a few minutes to complete, and a function that is short-running and latency-critical, e.g.,
using Dates # required to print inter-service times
function heartbeat()
dim = 1000
A = rand(dim, dim)/dim
t = now()
while (true)
A^256
println("alive: $(now()-t)")
t = now()
end
end
whose individual iterations in the while loop typically take less than a second to complete (if run separately).
I’m calling this function using julia -t auto
as follows
routines = [longrun, heartbeat]
@sync for routine in routines
Threads.@spawn routine()
end
As I have plenty of resources, I’d naively expect the heartbeat function to print continuously, independently of the long-running function.
This is however not the case. The long-running function seems to block the heartbeat function almost entirely:
alive: 447 milliseconds
starting exponentiation
alive: 391 milliseconds
exponentiation done
alive: 136699 milliseconds
alive: 205 milliseconds
alive: 265 milliseconds
I’m aware that this is a known problem (e.g., see How to perform ongoing background work with a real time ui - #4 by tkf), but I’m not sure how to tackle it best (without introducing dedicated processes). I’ve also tried reducing the number of BLAS threads, or using a Julia-native matrix multiplication library instead (Octavian.jl), but the issue remained.
I suspect that using two different thread pools (as introduced with 1.9) may be an option, but I fail to see how exactly.
Any suggestions would be more than welcome. I’m using Julia v1.9 on Linux.
Here’s the full code (including a failed attempt at using 1.9’s interactive feature):
using Dates
function longrun()
dim = 20000
A = rand(dim,dim)/dim
println("starting exponentiation")
A^256
println("exponentiation done")
end
function heartbeat()
dim = 1000
A = rand(dim, dim)/dim
t = now()
while (true)
A^256
println("alive: $(now()-t)")
t = now()
end
end
@sync begin
Threads.@spawn :interactive heartbeat()
Threads.@spawn longrun()
end