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.