Libtask
Tape based task copying in Turing
Getting Started
Stack allocated objects are always deep copied:
using Libtask
function f()
t = 0
for _ in 1:10
produce(t)
t = 1 + t
end
end
ttask = TapedTask(f)
@show consume(ttask) # 0
@show consume(ttask) # 1
a = copy(ttask)
@show consume(a) # 2
@show consume(a) # 3
@show consume(ttask) # 2
@show consume(ttask) # 3
Heapallocated Array and Ref objects are deep copied by default:
using Libtask
function f()
t = [0 1 2]
for _ in 1:10
produce(t[1])
t[1] = 1 + t[1]
end
end
ttask = TapedTask(f)
@show consume(ttask) # 0
@show consume(ttask) # 1
a = copy(ttask)
@show consume(a) # 2
@show consume(a) # 3
@show consume(ttask) # 2
@show consume(ttask) # 3
Other heapallocated objects (e.g., Dict
) are shallow copied, by default:
using Libtask
function f()
t = Dict(1=>10, 2=>20)
while true
produce(t[1])
t[1] = 1 + t[1]
end
end
ttask = TapedTask(f)
@show consume(ttask) # 10
@show consume(ttask) # 11
a = copy(ttask)
@show consume(a) # 12
@show consume(a) # 13
@show consume(ttask) # 14
@show consume(ttask) # 15
Notes:

The Turing probabilistic programming language uses this task copying feature in an efficient implementation of the particle filtering sampling algorithm for arbitrary order Markov processes.

From v0.6.0, Libtask is implemented by recording all the computing to a tape and copying that tape. Before that version, it is based on a tricky hack on the Julia internals. You can check the commit history of this repo to see the details.