# In-place assignment, without allocation

**URL:** https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811
**Category:** Performance
**Tags:** indexing, inplace
**Created:** [September 13, 2023, 12:37pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811 "2023-09-13T12:37:06Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)
#### Post date: [September 13, 2023, 12:37pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/1 "2023-09-13T12:37:06Z")

</div>

I’m trying to do `y = x[ind]` in-place, where `y, x, ind` are all vectors. By in-place, I mean no memory is allocated. I’m able to achieve this using a hand-written for loop (`assign2!` below). I suspect there is a way to achieve this using broadcasting, which could potentially generate better code. However, I haven’t been able to find it. `assign!` below is my attempt at it. Is there a simple line of code using broadcasting that works (doesn’t allocate, & is fast)? Why doesn’t the `@.` find it?

```julia
using BenchmarkTools, Random

x = randn(100)
y = zeros(200)
ind = vcat(randperm(100), randperm(100))

assign!(y, x, ind) = @inbounds @. y = x[ind]

@btime assign!($y, $x, $ind);

function assign2!(y, x, ind)
    @simd for i in eachindex(ind)
        @inbounds y[i] = x[ind[i]]
    end
end

@btime assign2!($y, $x, $ind);

```

---

<div class="post-metadata">

### Author: ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)
#### Post date: [September 13, 2023, 1:01pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/2 "2023-09-13T13:01:30Z")

</div>

```julia
assign!(y,x,ind) = y.=getindex.(Ref(x), ind)

```

is allocation free. The problem in your example is that `x[ind]` is not a `broadcasted`, hence it doesn’t fuse with the assignment.

By the way, the `@simd` is useless here.

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [September 13, 2023, 1:02pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/3 "2023-09-13T13:02:09Z")

</div>

EDIT: I think I misunderstood the question - sorry.  
Granted, this has one allocation, but this seems pretty fast to me:

```julia
x = randn(10)
y = zeros(10)
@btime y .= x
  22.051 ns (1 allocation: 16 bytes)

```

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [September 13, 2023, 1:11pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/4 "2023-09-13T13:11:19Z")

</div>

Why is it that this does not allocate:

```julia
@btime assign!(y, x, 3)
  10.063 ns (0 allocations: 0 bytes)

```

… but this does?

```julia
@btime y .= getindex.(x, 3)
  19.719 ns (1 allocation: 32 bytes)

```

---

<div class="post-metadata">

### Author: ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)
#### Post date: [September 13, 2023, 1:12pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/5 "2023-09-13T13:12:41Z")

</div>

> [@frylock](#):
>
> Granted, this has one allocation, but this seems pretty fast to me

Regardless of the speed, it is strange to me that this allocates.

---

<div class="post-metadata">

### Author: ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)
#### Post date: [September 13, 2023, 1:15pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/6 "2023-09-13T13:15:07Z")

</div>

You need to do `@btime $y .= $x`, which shows no allocations.

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [September 13, 2023, 1:15pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/7 "2023-09-13T13:15:45Z")

</div>

I’m not yet good enough to unravel everything, but the best I can figure is if I wrote it in C, it would look something like:

```plaintext
int x[10];
int y[10]; // or whatever

for (int i = 0; i < 10; ++i)
    y[i] = x[i];

```

The allocation would be the loop variable?

---

<div class="post-metadata">

### Author: ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)
#### Post date: [September 13, 2023, 1:15pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/8 "2023-09-13T13:15:54Z")

</div>

> [@frylock](#):
>
> Granted, this has one allocation

> [@user664303](#):
>
> Regardless of the speed, it is strange to me that this allocates.

> [@frylock](#):
>
> … but this does?

It doesn’t, but you must remember to interpolate external variables in benchmark expressions

```julia
julia> @btime $y .= $x
  15.415 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

### Author: ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)
#### Post date: [September 13, 2023, 1:17pm UTC](https://discourse.julialang.org/t/in-place-assignment-without-allocation/103811/9 "2023-09-13T13:17:45Z")

</div>

> [@frylock](#):
>
> The allocation would be the loop variable?

No, “allocation” means heap allocation which need to be tracked and eventually garbage collected. That counter would live happily on the stack.
