I thought the view function worked something like a refererence in c++, basically both variables are pointing to the same piece of memory.
Why does this work:
julia> a = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
1 2 3
4 5 6
7 8 9
julia> b = view(a, 1, :)
3-element view(::Array{Int64,2}, 1, :) with eltype Int64:
1
2
3
julia> b[1] = 100
100
julia> a
3×3 Array{Int64,2}:
100 2 3
4 5 6
7 8 9
julia> a[1, 3] = 200
200
julia> b
3-element view(::Array{Int64,2}, 1, :) with eltype Int64:
100
2
200
Basically you change one and the other changes, too, and vice versa. But this doesn't have the same effect:
julia> a = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
1 2 3
4 5 6
7 8 9
julia> a[3, :] = view(a, 1, :)
3-element view(::Array{Int64,2}, 1, :) with eltype Int64:
1
2
3
julia> a
3×3 Array{Int64,2}:
1 2 3
4 5 6
1 2 3
julia> a[1, 1] = 100
100
julia> a
3×3 Array{Int64,2}:
100 2 3
4 5 6
1 2 3
julia> a[3, 1] = 200
200
julia> a
3×3 Array{Int64,2}:
100 2 3
4 5 6
200 2 3
My question: Is that equivalent to just doing: a[3, :] = a[1, :]
? Do either have any performance benefits? What is happening behind the scenes on that second scenario?
Any feedback is appreciated!
You can check that copying in this case happens e.g. by running this code:
julia> a = rand(3, 10^6);
julia> b = view(a, 1, :);
julia> @time a[3, :] = b; # I have already compiled the code earlier
0.005599 seconds (3 allocations: 7.629 MiB)
julia> bc = copy(b);
julia> @time a[3, :] = bc; # I have already compiled the code earlier
0.002189 seconds (1 allocation: 16 bytes)
The reason is that Julia in function _unsafe_setindex!
(that is in the end called by the operation you do), does x′ = unalias(A, x)
. This operation means that it is checked if source and destination arrays are guaranteed not to share memory at compile time. In this case the compiler is not able to prove this, so copying happens.
What you could do to make the operation you want efficient is just to use a loop (as you know that actually aliasing does not happen by the way you have defined your operation; I am using a view but of course you could just read and write from a
directly without creating b
):
function fastcopy!(a)
@assert size(a, 1) > 2
b = view(a, 1, :)
@inbounds @simd for i in eachindex(b)
a[3, i] = b[i]
end
end
and here you have the timing:
julia> @time fastcopy!(a)
0.001895 seconds
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With