# Allocations with closure and mul!

**URL:** <https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744>\
**Category:** Performance\
**Tags:** memory-allocation, closure\
**Created:** [May 7, 2021, 9:35pm UTC](https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744 "2021-05-07T21:35:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![geoffroyleconte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/geoffroyleconte/32/21661_2.png) [@geoffroyleconte](https://discourse.julialang.org/u/geoffroyleconte)\
**Post date:** [May 7, 2021, 9:35pm UTC](https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744/1 "2021-05-07T21:35:51Z")

</div>

Hi! I have an issue with allocations using the `mul!` function and a closure:

```julia
using LinearAlgebra, Test

struct operator{T} 
    prod!
end

function operator(A :: AbstractArray{T}) where T 
    prod! = (res, u, α, β) -> mul!(res, A, u, α, β)
    return operator{T}(prod!)
end

import LinearAlgebra.mul!

function mul!(res::Vector{T}, op::operator{T}, u::Vector{T}, α::T, β::T) where T 
    op.prod!(res, u, α, β)
end

function mul!(res::Vector{T}, op::operator{T}, u::Vector{T}) where T 
    op.prod!(res, u, one(T), zero(T))
end

function mul2!(res::Vector{T}, op::operator{T}, u::Vector{T}) where T 
    op.prod!(res, u, 2*one(T), 2*one(T))
end

function test_allocs()
    n = 10
    A = rand(n, n)
    A_op1 = operator(A)
    res1, u1, α1, β1 = rand(n), rand(n), 2.0, 2.0

    ### compile
    A_op1.prod!(res1, u1, β1, α1)
    mul!(res1, A_op1, u1, β1, α1)  
    mul!(res1, A, u1, α1, β1) 
    mul2!(res1, A_op1, u1) 

    ### tests allocs
    allocs1 = @allocated A_op1.prod!(res1, u1, α1, β1) 
    @test allocs1 == 16
    allocs2 = @allocated mul!(res1, A_op1, u1, α1, β1)
    @test allocs2 == 32
    allocs3 = @allocated mul!(res1, A, u1, α1, β1) # LinearAlgebra mul! function for matrices
    @test allocs3 == 0
    allocs4 = @allocated mul!(res1, A_op1, u1) 
    @test allocs4 == 0
    allocs5 = @allocated mul2!(res1, A_op1, u1) 
    @test allocs5 == 0
end

test_allocs()

```

All tests passed but I do not know how to remove the allocations for the first and second tests with my type `operator{T}`. Maybe it comes from `α` and `β` because when I removed them with the 3-args `mul!` and `mul2!` the allocations disappear, but I could not find a way to solve this problem. Does anybody know how I could fix this?

---

<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:** [May 9, 2021, 6:20am UTC](https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744/2 "2021-05-09T06:20:53Z")

</div>

The field `prod!` of your `operator` type misses a type annotation and hence seems to be of `Any`. I assume you wanted to make this `prod!::T`.

---

<div class="post-metadata">

**Author:** ![geoffroyleconte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/geoffroyleconte/32/21661_2.png) [@geoffroyleconte](https://discourse.julialang.org/u/geoffroyleconte)\
**Post date:** [May 10, 2021, 1:33pm UTC](https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744/3 "2021-05-10T13:33:53Z")

</div>

I do not think that this possible because I want `prod!` to be a closure (its type could be `Function` but it does not change the number of allocations). The `T` in `struct operator{T}` is only used to indicate that the closure should work with data of type `T`.

---

<div class="post-metadata">

**Author:** ![david-pl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/david-pl/32/6224_2.png) [@david-pl](https://discourse.julialang.org/u/david-pl)\
**Post date:** [May 10, 2021, 2:07pm UTC](https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744/4 "2021-05-10T14:07:31Z")

</div>

If you want to reserve `T` for data you can just add another type parameter to `operator` to make `prod!` type-stable:

```julia
struct operator{T,F}
    prod!::F
end
operator{T}(prod!::F) where {T,F} = operator{T,F}(prod!)

```

---

<div class="post-metadata">

**Author:** ![geoffroyleconte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/geoffroyleconte/32/21661_2.png) [@geoffroyleconte](https://discourse.julialang.org/u/geoffroyleconte)\
**Post date:** [May 10, 2021, 2:19pm UTC](https://discourse.julialang.org/t/allocations-with-closure-and-mul/60744/5 "2021-05-10T14:19:44Z")

</div>

Thank you!
