Status of "let" statements before Threads.@threads

Hello! I found myself using a lot of let statements before multi-threaded for-loops with the Threads.@threads command in my code. I wanted to know if these were still useful in the present version of julia now. Does anyone know the status of this declaration?

For an example:

function withlet(g::Int64)
  b = 1.4
  A = Array{Float64,1}(undef,g)
  let A = A, b = b, g = g
    Threads.@threads for i = 1:g
      A[i] = b
    end
  end
end


function nolet(g::Int64)
  b = 1.4
  A = Array{Float64,1}(undef,g)
#  let A = A, b = b, g = g
    Threads.@threads for i = 1:length(A)
      A[i] = b
    end
#  end
end

The reason I ask is because there doesn’t seem to be a different in this simple example:

julia> using BenchmarkTools
julia> @btime withlet(5000_000)
  2.954 ms (23 allocations: 38.15 MiB)

julia> @btime nolet(5000_000)
  3.043 ms (23 allocations: 38.15 MiB)

I seem to remember that using the let statement can reduce the allocations in a given function, but I can’t find the post where I saw that (circa v1.2). Is there any use to using the let statements?

The official documentation

https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Let-Blocks

currently states: Unlike assignments to local variables, let statements allocate new variable bindings each time they run. Moreover, let introduces a new scope block. I think these are the main features, why someone would use them.

I am pretty sure this is just noise, there shouldn’t be a performance difference in this particular example.

This is potentially misleading. A new binding doesn’t mean any objects get allocated at runtime.

1 Like

That is true.

Running the benchmarks a couple of times, I observe quite some variation of the results. I would say the differences you observe can likely be attributed to measurement noise.

Thanks everyone for their responses. Yes, I think the difference in time is only measurement noise.

I couldn’t find the documentation, but @moeddel provided it, and that answered my questions. The let blocks are necessary when you recycle a variable, in one particular case (see documentation). I suspect I had that in my code at one point and this fixed it, so that might be why I had it in there. But it is not necessary all the time. Thank you!

1 Like