Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is happening behind the scenes in julia's view function? a[3, :] = view(a, 1, :) vs a[3, :] = a[1, :]

Tags:

julia

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!

like image 580
Belen Avatar asked Jan 31 '21 13:01

Belen


Video Answer


1 Answers

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
like image 177
Bogumił Kamiński Avatar answered Sep 27 '22 20:09

Bogumił Kamiński