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 ?
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 ?
Can’t answer the second question, but that case is what x .+= y is for.
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.
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.
Thanks, I deleted my post so as not to mislead future readers.