Hey there,
I am desperately trying to figure out how to do some “real” multi-threadding in Julia. What do I mean by that: My program consists of three tasks: the main task and two separate task I start. I need to communicate from the main task to the two separte tasks via channels. This is how I start my desired background task:
c = Channel{Bool}(1, spawn=true) do c # create new channel with buffersize 1
status = false
while isopen(c)
if isready(c) # determine whether the channel `c` has a value stored to it; returns immediately, does not block
status = fetch(c) # wait for and get the available item from the channel `c`
end
@info "$(Dates.now()) status is $status"
t_now = Dates.now()
while Dates.now() < t_now + Dates.Second(10)
sleep(1) # [s]
end
end
@info "channel closed, background task will terminate"
end
I update the channel value by
function updateChannelValue!(c::Channel, value::Bool)
# Since the channel capacity is only one and `put!` blocks if there is
# already a value present, we must first make sure to remove the element stored there.
lock(c)
try
if isready(c) # determine whether the channel `c` has a value stored to it; returns immediately, does not block
take!(c) # remove old value from channel
end
put!(c,value)
finally
unlock(c)
end
return
end
updateChannelValue!(c, true)
So far everything works like expected. But If i do
for i = 1:10_000
x = rand(100_000)
y = x.^2 .+ log.(x) + x.^10 + log10.(x)
end
I can see that until the loop is finished there is no output from the background task. However, if I do
for i = 1:10_000
x = rand(100_000)
y = x.^2 .+ log.(x) + x.^10 + log10.(x)
yield() # switch to the scheduler to allow another scheduled task to run
end
It works as I would like it. The problem is that this is just an example. I my real code I could have (pure Julia and non-pure Julia) calls that takes longer than e.g. 60 seconds and I want my background task to run at least (more or less reliable) every 60 seconds.
Here is the whole test script:
@info "Julia has $(Threads.nthreads()) cores available"
@info "REPL runs on core $(Threads.threadid())"
c = Channel{Bool}(1, spawn=true) do c # create new channel with buffersize 1
@info "Background task runs on core $(Threads.threadid())"
status = false
while isopen(c)
if isready(c) # determine whether the channel `c` has a value stored to it; returns immediately, does not block
status = fetch(c) # wait for and get the available item from the channel `c`
end
@info "$(Dates.now()) status is $status"
t_now = Dates.now()
while Dates.now() < t_now + Dates.Second(10)
sleep(1) # [s]
end
end
@info "channel closed, background task will terminate"
end
function updateChannelValue!(c::Channel, value::Bool)
# Since the channel capacity is only one and `put!` blocks if there is
# already a value present, we must first make sure to remove the element stored there.
lock(c)
try
if isready(c) # determine whether the channel `c` has a value stored to it; returns immediately, does not block
take!(c) # remove old value from channel
end
put!(c,value)
finally
unlock(c)
end
return
end
sleep(30)
updateChannelValue!(c, true)
sleep(60)
@info "call blocking code"
# this will block the background task until finished
for i = 1:10_000
x = rand(100_000)
y = x.^2 .+ log.(x) + x.^10 + log10.(x)
end
@info "call non-blocking code"
# this won't block the background task
for i = 1:10_000
x = rand(100_000)
y = x.^2 .+ log.(x) + x.^10 + log10.(x)
yield() # switch to the scheduler to allow another scheduled task to run
end
close(c)
and the output on my machine:
[ Info: Julia has 2 cores available
[ Info: REPL runs on core 1
[ Info: Background task runs on core 2
[ Info: 2022-03-15T17:02:10.591 status is false
[ Info: 2022-03-15T17:02:20.624 status is false
[ Info: 2022-03-15T17:02:30.664 status is false
[ Info: 2022-03-15T17:02:40.696 status is true
[ Info: 2022-03-15T17:02:50.743 status is true
[ Info: 2022-03-15T17:03:00.781 status is true
[ Info: 2022-03-15T17:03:10.822 status is true
[ Info: 2022-03-15T17:03:20.854 status is true
[ Info: 2022-03-15T17:03:30.902 status is true
[ Info: call blocking code
[ Info: call non-blocking code
[ Info: 2022-03-15T17:05:15.381 status is true
[ Info: 2022-03-15T17:05:25.537 status is true
[ Info: 2022-03-15T17:05:35.591 status is true
[ Info: 2022-03-15T17:05:45.672 status is true
[ Info: 2022-03-15T17:05:55.729 status is true
[ Info: 2022-03-15T17:06:05.808 status is true
[ Info: 2022-03-15T17:06:15.926 status is true
[ Info: 2022-03-15T17:06:25.970 status is true
[ Info: 2022-03-15T17:06:36.055 status is true
Hope there is any hint … what I could do