In place updating of arrays

If we have array equation like

x = x + y

this creates extra memory allocation. Does the following do in place update

x .= x + y

How to find out if the update is happening in place ?

1 Like

Can’t answer the second question, but that case is what x .+= y is for.

1 Like

The best way to check if this is happening in place is @allocated (or @time).

I had a surprisingly difficult time running tests on this, because Julia seems to be quite smart about optimizing it. For example:

julia> a = rand(100);

julia> b = rand(100);

julia> c = zeros(100);

julia> using BenchmarkTools

julia> @btime c = a + b;
  73.847 ns (1 allocation: 896 bytes)

The fact that it does just one allocation suggests to me that julia is already doing c = a + b in place, even without .=, although maybe I’m missing something.

That’s weird. That said, in general, doing these tests in the global scope will often lead you astray. What happens if you try f!(c,a,b) = (c = a+b)?

It is indeed clever about that, but your case is not the same as in the question. It’s x = x + y, not z = x + y

Julia is doing everything correctly. Operation a + b requires 1 allocation to create a new array and c = ... binds variable c to this new array. Binding does not require allocation.

In other words, c = a + b is roughly equivalent to

temp = Vector{Float64}(undef, 100)
for i in 1:100
   temp[i] = a[i] + b[i]
end
c = temp

If you want inplace operation, you need to use . both in + and =. Then this operations are fused together and turns into inplace update. I.e. c .= a .+ b is equivalent to

for i in 1:100
  c[i] = a[i] + b[i]
end

UPD: operation c .= a + b is rather meaningless, because it is equivalent to

temp = Vector{Float64}(undef, 100)
for i in 1:100
   temp[i] = a[i] + b[i]
end

for i in 1:100
  c[i] = temp[i]
end

so it run even slower than c = a + b because instead of binding variable, it copies data.

7 Likes

You are benchmarking with global variables, so the allocations are going crazy (you should be seeing zero or 1 or 2 allocations, not hundreds of thousands).

Use BenchmarkTools.jl, don’t use the @time macro for micro-benchmarks, and avoid global variables.

3 Likes

Thanks, I deleted my post so as not to mislead future readers.