Thread-local let bindings?

I’m running into performance problems when my multithreaded code allocates heavily, so I’m trying to use let bindings to avoid reallocating large arrays, but I don’t see any way to make the bindings thread-local.

For example, I don’t think the following is thread-safe:

const rngs = ntuple(Random.MersenneTwister, Threads.nthreads())

let a = zeros(10^6)
    global function f()
        rand!(rngs[Threads.threadid()], a)
        sum(a)
    end
end

Threads.@threads for _ in 1:100 
    f()
end  

Perhaps you could define a struct to hold your buffer (and perhaps also your RNG) and then define your function to act on that struct?

struct Foo
  a::Vector{Float64}
  rng::(whatever the correct type is)
end

function f!(f::Foo)
 (do stuff with f.a and f.rng)
end

buffers = [Foo(...) for _ in 1:Threads.nthreads()]
Threads.@threads for _ in 1:100  
  f!(buffers[Threads.threadid()]
end
1 Like