# Can I avoid allocations when broadcasting over slices?

**URL:** <https://discourse.julialang.org/t/can-i-avoid-allocations-when-broadcasting-over-slices/102501>\
**Category:** Performance\
**Created:** [August 4, 2023, 7:08pm UTC](https://discourse.julialang.org/t/can-i-avoid-allocations-when-broadcasting-over-slices/102501 "2023-08-04T19:08:51Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [August 4, 2023, 7:08pm UTC](https://discourse.julialang.org/t/can-i-avoid-allocations-when-broadcasting-over-slices/102501/1 "2023-08-04T19:08:51Z")

</div>

I was a little surprised to find that broadcasting over slices allocates, even when using `view`. Here’s a MWE.

```julia
u = randn(10, 100)
ids = reshape(1:100, 10, 10)
out = similar(u[ids])

function foo1!(out, u, ids)
    @. out = u[ids] 
    # FastBroadcast.@.. does slightly better, but 
    # still allocates as much as `view(u, ids)`
end
function foo2!(out, u, ids)
    out .= view(u, ids)
end
function foo3!(out, u, ids)
    for (i, id) in enumerate(ids)
        out[i] = u[id]
    end
end

# run once for compilation 
foo1!(out, u, ids); foo2!(out, u, ids); foo3!(out, u, ids);

# timings
@time foo1!(out, u, ids);
@time foo2!(out, u, ids);
@time foo3!(out, u, ids);

```

I see this for both 1.9.2 and 1.10-beta on Mac ARM.

Is there a way to avoid allocations without resorting to for loops?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 4, 2023, 7:14pm UTC](https://discourse.julialang.org/t/can-i-avoid-allocations-when-broadcasting-over-slices/102501/2 "2023-08-04T19:14:33Z")

</div>

You’re doing linear indexing into a matrix, which is implicitly doing a reshape under the hood when you take the `view`. That’s your allocation — it’s in the `view`, not the broadcast.

```plaintext
julia> @time foo2!(out, u, ids);
  0.000012 seconds (2 allocations: 80 bytes)

julia> v = reshape(u, :);

julia> @time foo2!(out, v, ids);
  0.000009 seconds

```

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [August 4, 2023, 7:19pm UTC](https://discourse.julialang.org/t/can-i-avoid-allocations-when-broadcasting-over-slices/102501/3 "2023-08-04T19:19:17Z")

</div>

One option here is to broadcast the indexing itself:

```julia
# use `Ref(u)` so that `u` is not broadcasted
out .= getindex.(Ref(u), ids)

```

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [August 4, 2023, 7:22pm UTC](https://discourse.julialang.org/t/can-i-avoid-allocations-when-broadcasting-over-slices/102501/4 "2023-08-04T19:22:19Z")

</div>

That’s helpful to know! Thanks for clarifying what’s happening internally.
