# Avoiding allocations from views: copyto! between arrays of different shape

**URL:** <https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980>\
**Category:** General Usage\
**Created:** [October 30, 2018, 6:46pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980 "2018-10-30T18:46:51Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 30, 2018, 6:46pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/1 "2018-10-30T18:46:51Z")

</div>

Say I have an n x m `Matrix`, and an n-length `Vector` that I want to copy to, say, column 2 of my matrix. My first try was to do `copyto!` using `CartesianIndices`.

```julia
m = rand(3,3)
v = rand(3)
copyto!(m, CartesianIndices((1:3, 2:2)), v, CartesianIndices(1:3))

```

But that fails. `copyto!` only works to copy a slice of an `AbstractArray{T1,N}` to another slice of an `AbstractArray{T2,N}`, i.e. between tensors with the same number of indices, despite the API very elegantly allows to express the more general case with `N1 != N2` as above. What is the proper way to do this (for arbitrary `N1`, `N2`) in v1.0? Is there a reason why we would not want a more general `copyto!`?

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 30, 2018, 7:03pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/2 "2018-10-30T19:03:34Z")

</div>

Something like the following (slight modification of the version in `Base`) seems to work for me. It’s such a minor modification that I suspect somebody had a good reason _not_ to do it…

```julia
function copyto!(dest::AbstractArray{T1,N1}, Rdest::CartesianIndices{N1}, src::AbstractArray{T2,N2}, Rsrc::CartesianIndices{N2}) where {T1,T2,N1,N2}
    checkbounds(dest, first(Rdest))
    checkbounds(dest, last(Rdest))
    checkbounds(src, first(Rsrc))
    checkbounds(src, last(Rsrc))
    src′ = unalias(dest, src)
    for (Is, Id) in zip(Rsrc, Rdest)
        @inbounds dest[Id] = src′[Is]
    end
    return dest
end

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 30, 2018, 8:34pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/3 "2018-10-30T20:34:03Z")

</div>

I might not understand your problem correctly, but is there a reason why e.g. `X[2,:] .= Y` does not work for you?

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 30, 2018, 10:00pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/4 "2018-10-30T22:00:52Z")

</div>

No, that works perfectly well, and it’s probably the truly Julian approach. The (small) problem is that, if I understand correctly, that approach allocates a `view`, and is therefore somewhat slower than a direct copy. Until we have something like [#14955](https://github.com/JuliaLang/julia/issues/14955) I prefer to avoid views in my particular application. But thanks for pointing that out!

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 30, 2018, 10:05pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/5 "2018-10-30T22:05:56Z")

</div>

To illustrate

```julia
a = rand(3,3); b = rand(3,3);
f1(a,b) = a[1:2, 2:3] .= b[2:3, 1:2]
f2(a,b) = copyto!(a, CartesianIndices((1:2, 2:3)), b, CartesianIndices((2:3, 1:2)))

```

on v1.0.1

```julia
julia> @btime f1($a,$b);
  61.395 ns (2 allocations: 176 bytes)
julia> @btime f2($a,$b);
  15.850 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 31, 2018, 6:14am UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/6 "2018-10-31T06:14:30Z")

</div>

> [@pablosanjose](#):
>
> The (small) problem is that, if I understand correctly, that approach allocates a `view`, and is therefore somewhat slower than a direct copy.

Note, that it only allocates a view of you have a slice on the rhs of the assignment. For copying a full vector (or matrix), as in your original example, it should be efficient.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 31, 2018, 6:43am UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/7 "2018-10-31T06:43:32Z")

</div>

Mmm, are you sure that’s always true? The following `f1` also seems to allocate a view, although indeed the performance is now much closer to `f2`

```julia
a = rand(3,3); b = rand(2,2);
f1(a,b) = a[1:2, 2:3] .= b
f2(a,b) = copyto!(a, CartesianIndices((1:2, 2:3)), b, CartesianIndices((1:2, 1:2)))

```

```julia
julia> @btime f1($a,$b)
  22.696 ns (1 allocation: 64 bytes)
2×2 view(::Array{Float64,2}, 1:2, 2:3) with eltype Float64:
 0.408094 0.413918
 0.0414806 0.610879

julia> @btime f2($a,$b)
  17.146 ns (0 allocations: 0 bytes)
3×3 Array{Float64,2}:
 0.8406 0.408094 0.413918
 0.664731 0.0414806 0.610879
 0.0776809 0.810417 0.810417

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 31, 2018, 6:48am UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/8 "2018-10-31T06:48:06Z")

</div>

I’m sorry, what I said isn’t the full story. it is still creating a view for the lhs. Only no slices at all should be equally fast. (I’m on phone)

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 31, 2018, 7:40am UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/9 "2018-10-31T07:40:15Z")

</div>

Even in the case of fully overwriting `a` by `b` the `copyto!` approach is a bit faster:

```julia
julia> f2(a,b) = copyto!(a, CartesianIndices((1:3, 1:3)), b, CartesianIndices((1:3, 1:3)))
f2 (generic function with 1 method)

julia> f1(a,b) = a.=b;

julia> @btime f1($a, $b);
  17.313 ns (0 allocations: 0 bytes)

julia> @btime f2($a, $b);
  20.756 ns (0 allocations: 0 bytes)

```

I see no reason not to have a more general `copyto!`.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 31, 2018, 2:43pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/10 "2018-10-31T14:43:28Z")

</div>

Ref [https://github.com/JuliaLang/julia/pull/29868](https://github.com/JuliaLang/julia/pull/29868).

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 31, 2018, 2:44pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/11 "2018-10-31T14:44:21Z")

</div>

> [@carstenbauer](#):
>
> Even in the case of fully overwriting `a` by `b` the `copyto!` approach is a bit faster

Your numbers suggest the opposite?

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 31, 2018, 2:46pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/12 "2018-10-31T14:46:19Z")

</div>

> [@kristoffer.carlsson](#):
>
> Ref [inline copyto! for SubArrays by KristofferC · Pull Request #29868 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/29868).

Wow, wait, what? Did you just elide the view allocation with @inline? Does it also work with a slice on the right side?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 31, 2018, 2:57pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/13 "2018-10-31T14:57:02Z")

</div>

That PR makes the RHS slice a bit better:

```julia
julia> a = rand(3,3); b = rand(3,3);

julia> f1(a,b) = (a[1:2, 2:3] .= b[2:3, 1:2]; nothing)

```

Before

```julia
julia> @btime f1($a,$b);
  79.742 ns (2 allocations: 176 bytes)

```

After

```julia
julia> @btime f1($a,$b);
  64.168 ns (1 allocation: 112 bytes)

```

~~There is still an allocation happening because equality between `AbstractArray` and `SubArray` is not inlined.~~

Actually I am not sure why.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 31, 2018, 3:21pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/14 "2018-10-31T15:21:05Z")

</div>

Apparently I confused myself with the order 🙂

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 31, 2018, 3:28pm UTC](https://discourse.julialang.org/t/avoiding-allocations-from-views-copyto-between-arrays-of-different-shape/16980/15 "2018-10-31T15:28:21Z")

</div>

It sure would be great if could work as efficiently as `copyto!`. Much simpler, and nicer, I would gladly use `.=` always and stop worrying about hidden allocations.
