I’m struggling to understand the in-place modification operator .=
in Julia 1.0+ in the following examples,
julia> b = rand(1000, 1000)
julia> @time begin
Ham = zeros(1000, 1000)
for i in 1:100
global Ham .= Ham .+ b
end
println(Ham[1, 1])
end
96.71386850591365
0.092689 seconds (215 allocations: 7.634 MiB, 1.67% gc time)
julia> @time begin
Ham = zeros(1000, 1000)
for i in 1:100
global Ham .= Ham + b
end
println(Ham[1, 1])
end
96.71386850591365
0.199746 seconds (416 allocations: 770.580 MiB, 2.23% gc time)
julia> @time begin
Ham = zeros(1000, 1000)
for i in 1:100
global Ham = Ham + b
end
println(Ham[1, 1])
end
96.71386850591365
0.264974 seconds (215 allocations: 770.577 MiB, 31.54% gc time)
It seems that the second option Ham .= Ham + b
still creates a tmp copy of Ham + b
, and only pair .=
it with .+
will we be able to avoid allocating the tmp copy. Why the implememtation/semantics did it in this way? What is wrong in implementing Ham .= Ham + b
to have the same effect as Ham .= Ham .+ b
?
Another problem I had is
julia> a = 1;
julia> a .= 1 .+ 1
ERROR: MethodError: no method matching copyto!(::Int64, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{0},Tuple{},typeof(+),Tuple{Int64,Int64}})
Closest candidates are:
copyto!(::AbstractArray, ::Base.Broadcast.Broadcasted{#s617,Axes,F,Args} where Args<:Tuple where F where Axes where #s617<:Base.Broadcast.AbstractArrayStyle{0}) at broadcast.jl:848
copyto!(::AbstractArray, ::Base.Broadcast.Broadcasted) at broadcast.jl:842
copyto!(::AbstractArray, ::Any) at abstractarray.jl:720
Stacktrace:
[1] materialize!(::Int64, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{0},Nothing,typeof(+),Tuple{Int64,Int64}}) at ./broadcast.jl:801
[2] top-level scope at REPL[22]:1
It seems to me .=
in-place modification, by definition, need a
to be mutable, for example an array instead of a primitive type Int
here. However, what surprise me is the error information. What is the relationship between .=
and copyto!
?