# Why these two functions have different allocations?

**URL:** https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517
**Category:** General Usage
**Created:** [July 12, 2021, 4:00pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517 "2021-07-12T16:00:47Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Fred\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fred_he/32/14298_2.png) [@Fred\_He](https://discourse.julialang.org/u/Fred_He)
#### Post date: [July 12, 2021, 4:00pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/1 "2021-07-12T16:00:47Z")

</div>

I want to avoid any excess allocation. The f1! below needs 2m+1 allocations while the f2! needs m+1 allocations.  
is ito possible to make this kind of functionality 1 allocation only?

```julia
function f1!(du, u)
    m,n = size(u)
    rAA = zeros(n)
    for i = 1:m
        A, B, C, D, E = u[i, :]
        rAA .= [0.1*A, 0.2*B, 0.1*C, 0.2*D, 0.1*E]
        lmul!(0.5, rAA)
        du[i,:] .= rAA
    end
end

```

```julia
function f2!(du, u)
    m,n = size(u)
    rAA = zeros(n)
    for i = 1:m
        A, B, C, D, E = u[i, :]
        rAA[1] = 0.1*A
        rAA[2] = 0.2*B
        rAA[3] = 0.1*C
        rAA[4] = 0.2*D
        rAA[5] = 0.1*E
        lmul!(0.5, rAA)
        du[i,:] .= rAA
    end
end

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [July 12, 2021, 4:02pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/2 "2021-07-12T16:02:56Z")

</div>

> [@Fred\_He](#):
>
> `[0.1*A, 0.2*B, 0.1*C, 0.2*D, 0.1*E]`

this needs allocation

---

<div class="post-metadata">

### Author: ![EP-Guy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ep-guy/32/3442_2.png) [@EP-Guy](https://discourse.julialang.org/u/EP-Guy)
#### Post date: [July 12, 2021, 4:23pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/3 "2021-07-12T16:23:24Z")

</div>

It seems like you can just annotate `@views` in the for loop:

```julia
function f3!(du, u)
    m,n = size(u)
    rAA = zeros(n)
    @views for i = 1:m
        A, B, C, D, E = u[i, :]
        rAA[1] = 0.1*A
        rAA[2] = 0.2*B
        rAA[3] = 0.1*C
        rAA[4] = 0.2*D
        rAA[5] = 0.1*E
        lmul!(0.5, rAA)
        du[i,:] .= rAA
    end
end

```

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 12, 2021, 4:29pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/4 "2021-07-12T16:29:50Z")

</div>

> [@Fred\_He](#):
>
> ` rAA .= [0.1*A, 0.2*B, 0.1*C, 0.2*D, 0.1*E]`

you can replace that by a tuple, and that should be non-allocating:

` rAA .= (0.1*A, 0.2*B, 0.1*C, 0.2*D, 0.1*E)`

---

<div class="post-metadata">

### Author: ![Fred\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fred_he/32/14298_2.png) [@Fred\_He](https://discourse.julialang.org/u/Fred_He)
#### Post date: [July 12, 2021, 4:30pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/5 "2021-07-12T16:30:13Z")

</div>

Thank you! This creats what I want. But… can you give some hints so I can figure out why? Thanks a lot!

---

<div class="post-metadata">

### Author: ![Fred\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fred_he/32/14298_2.png) [@Fred\_He](https://discourse.julialang.org/u/Fred_He)
#### Post date: [July 12, 2021, 4:33pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/6 "2021-07-12T16:33:16Z")

</div>

Thanks also! Then i don’t have to write excess code to assign values for each elements.

---

<div class="post-metadata">

### Author: ![EP-Guy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ep-guy/32/3442_2.png) [@EP-Guy](https://discourse.julialang.org/u/EP-Guy)
#### Post date: [July 12, 2021, 4:36pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/7 "2021-07-12T16:36:05Z")

</div>

Yes I prefer the notation of @lmiq too. The `u[i,:]` allocates, so annotating the `view` on that is enough to remove it.

```julia
function f4!(du, u)
    m,n = size(u)
    rAA = zeros(n)
    for i = 1:m
        A, B, C, D, E = @view u[i, :]
        rAA .= (0.1*A, 0.2*B, 0.1*C, 0.2*D, 0.1*E)
        lmul!(0.5, rAA)
        du[i,:] .= rAA
    end
end

```

Also, note that it may be faster to permute `u` so that when you extract `A, B, C, D, E` it happens in column major order (i.e. you’ll have `u[:,i]`).

---

<div class="post-metadata">

### Author: ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)
#### Post date: [July 12, 2021, 4:36pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/8 "2021-07-12T16:36:29Z")

</div>

`u[i, :]` allocates a new vector, so avoid that as well.

```julia
function f2!(du, u)
    m,n = size(u)
    rAA = zeros(n)
    for i = 1:m
        rAA[1] = 0.1*u[i, 1]
        rAA[2] = 0.2*u[i, 2]
        rAA[3] = 0.1*u[i, 3]
        rAA[4] = 0.2*u[i, 4]
        rAA[5] = 0.1*u[i, 5]
        lmul!(0.5, rAA)
        du[i,:] .= rAA
    end
end

```

Some more notes if you care about actual speed and not just allocations:

- Julia arrays are column-major, so `u[i,:]` and `du[i,:]` is not the preferred order of accessing these (if they are actual `Array`s).
- ~~The last two lines in the loop operate on the complete array `rAA` even though only the first 5 elements of `rAA` ever change. This could be easily avoided.~~ It looks like `rAA` only has five elements (I looked at `f2!` where that isn’t necessarily the case).

---

<div class="post-metadata">

### Author: ![Fred\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fred_he/32/14298_2.png) [@Fred\_He](https://discourse.julialang.org/u/Fred_He)
#### Post date: [July 12, 2021, 4:47pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/9 "2021-07-12T16:47:41Z")

</div>

Thank you! I understand Julia is column-major I have to use like this because in my code each line is the concentration of different species at one location. The calculation of rAA is not as simple as the code here but requires the concentration of different species.  
But do you think coding like

```julia
A = @view u[1, :]
B = @view u[2, :]
...

```

and call `A[i]` `B[i]` in the loop will be better?

---

<div class="post-metadata">

### Author: ![EP-Guy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ep-guy/32/3442_2.png) [@EP-Guy](https://discourse.julialang.org/u/EP-Guy)
#### Post date: [July 12, 2021, 5:02pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/10 "2021-07-12T17:02:54Z")

</div>

I wouldn’t expect that to perform any better. It could actually be worse with `u` in it’s current shape because of the memory access order, but you won’t know until you try it.

Same with permuting `u`. Maybe outside this function you need `u` in the shape it is now, but depending on its dimensions, the function might be faster for your application if inside the function you `permutedims(u)`. This makes a copy (costs allocations and time) but then extracting the elements will be faster - this may or may not be faster overall. I tried it here with `u` sized `(300, 5)` and it wasn’t worth it to `permutedims(u)` inside the function `f4!`.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 12, 2021, 5:07pm UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/11 "2021-07-12T17:07:33Z")

</div>

The best you can do there is probably to use static arrays:

```julia
julia> using StaticArrays
       function f5!(du, u::Vector{T}) where T
           r = T(0.1,0.2,0.1,0.2,0.1)
           for i = 1:length(u)
               du[i] = 0.5*(r .* u[i])
           end
       end
f5! (generic function with 2 methods)

julia> u = [1 .+ zero(SVector{5,Float64}) for i in 1:5];

julia> du = copy(u);

julia> @btime f5!($u2,du2)
  17.075 ns (0 allocations: 0 bytes)

```

(probably the code needs some adaptation to actually fit your real use case)

or, if you want to keep `u` and `du` as matrices:

```julia
julia> function f4!(du, u)
           m,n = size(u)
           for i = 1:m
               A, B, C, D, E = @view u[i, :]
               rAA = SVector{5,Float64}(0.1*A, 0.2*B, 0.1*C, 0.2*D, 0.1*E)
               du[i,:] .= 0.5*rAA
           end
       end
f4! (generic function with 1 method)

julia> @btime f4!($du,$u)
  27.456 ns (0 allocations: 0 bytes)

```

The issue in this last example is that the `5` must be known at compile time. Thus, if it varies, you must find a way to put it in the type information of the input variables of the function.

---

<div class="post-metadata">

### Author: ![Fred\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fred_he/32/14298_2.png) [@Fred\_He](https://discourse.julialang.org/u/Fred_He)
#### Post date: [July 13, 2021, 8:19am UTC](https://discourse.julialang.org/t/why-these-two-functions-have-different-allocations/64517/12 "2021-07-13T08:19:39Z")

</div>

Thank you! this also gives me new insight!
