# Allocation using broadcasting with custom type

**URL:** <https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592>\
**Category:** General Usage\
**Created:** [July 2, 2017, 12:05am UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592 "2017-07-02T00:05:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![gasagna](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gasagna/32/1275_2.png) [@gasagna](https://discourse.julialang.org/u/gasagna)\
**Post date:** [July 2, 2017, 12:05am UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/1 "2017-07-02T00:05:24Z")

</div>

Hi,

I am seeing some suspect allocations using broadcasting defined on a custom type, in particular when the broadcast involves `Number`s. The MWE is reported below. My actual code is somewhat larger but this example reproduce the behaviour.

```julia
struct Foo{T, A<:AbstractMatrix{T}} <: AbstractMatrix{T}
    data::A
end
Foo(data::A) where {A<:AbstractMatrix} = Foo{eltype(data), A}(data)

@inline Base.unsafe_get(f::Foo) = f.data

# Catch call to broadcast, then rebroadcast to field data
@generated function Base.Broadcast.broadcast!(f, dest::Foo, src::Vararg{Any, N}) where N
    args = [:(unsafe_get(src[$k])) for k = 1:N]
    quote
        broadcast!(f, unsafe_get(dest), $(args...))
        return dest
    end
end

# function that allocates
function bar(out, c::Number, x) 
    for i = 1:10000
        out .= x .* c
    end
    out
end

x = Foo(randn(100, 100))
out = Foo(randn(100, 100))
c = 1.0

@show @allocated bar(out, c, x)
@show @allocated bar(out, c, x)
@show @allocated bar(out, c, x)
@show @allocated bar(out, c, x)

```

The type `Foo` is the type I want to do broadcasting on, e.g., in the function `bar`. I have overloaded `broadcast!` on my custom type using a generated function approach. The above code results in

```julia
@allocated(bar(out, c, x)) = 3955676
@allocated(bar(out, c, x)) = 160000
@allocated(bar(out, c, x)) = 160000
@allocated(bar(out, c, x)) = 160000

```

If you change the line in the loop in `bar` to `out .= x .* x`, all allocations disappear. Any pointers are welcome.

Thanks

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [July 2, 2017, 8:23pm UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/2 "2017-07-02T20:23:12Z")

</div>

Looks like there are two issues: slatting, and specialization on the function (by default specialization only happens if function is called). This gets rid of allocations:

```julia
function Base.Broadcast.broadcast!{F}(f::F, dest::Foo, src1, src2)
    broadcast!(f, unsafe_get(dest), unsafe_get(src1), unsafe_get(src2))
    return dest
end

```

I’m not sure whether there’s a way of avoiding allocations and still use splatting. However, note that the allocation is only 16 bytes per iteration, so if the array is large this may not matter in practice (no copy of the array is made).

BTW, [this thread](https://discourse.julialang.org/t/broadcast-for-custom-type/3497/3) might be useful.

---

<div class="post-metadata">

**Author:** ![gasagna](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gasagna/32/1275_2.png) [@gasagna](https://discourse.julialang.org/u/gasagna)\
**Post date:** [July 2, 2017, 8:51pm UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/3 "2017-07-02T20:51:02Z")

</div>

Thanks! I was getting crazy at understanding why this happens. Note that it only does it with custom types and it does not allocate when arrays are used in the dot notation (bug? can be fixed?)

The allocation is small, but annoying.

Follow-up question: I need to generate many version of this function for different number of arguments.

This code does what I need, I am reporting it here in case someone will ever face a similar issue.

```julia
for nargs = 1:10
    args = [Symbol("src", i) for i = 1:nargs]
    calls = [:(unsafe_get($(args[i]))) for i = 1:nargs]
    @eval @generated function broadcast_c!(f, ::Type{FTField}, ::Type{FTField}, dest, $(args...))
            :(broadcast!(f, unsafe_get(dest), $($calls...)))
          end    
end 

```

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [July 3, 2017, 8:06am UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/4 "2017-07-03T08:06:29Z")

</div>

> [@gasagna](#):
>
> . Note that it only does it with custom types and it does not allocate when arrays are used in the dot notation (bug? can be fixed?)

A possible explanation is that the code for `Array` uses `@inline` annotations for functions with varargs, and functions which are not inlined take a tuple of arrays rather than varargs. You could take inspiration from it.

---

<div class="post-metadata">

**Author:** ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)\
**Post date:** [July 3, 2017, 10:00am UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/5 "2017-07-03T10:00:32Z")

</div>

I might be wrong, but it’s possible that these allocations will go away when non-`isbits` structs are stored unboxed (I’m guessing this is an non-inlining varargs call that passes a tuple, and the tuple needs to be constructed on the heap…). I.e. Hopefully it’s just a (known) compiler improvement away.

---

<div class="post-metadata">

**Author:** ![gasagna](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gasagna/32/1275_2.png) [@gasagna](https://discourse.julialang.org/u/gasagna)\
**Post date:** [July 3, 2017, 11:21am UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/6 "2017-07-03T11:21:29Z")

</div>

Do you mean in the broadcast code? Could you provide an example in Base?

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [July 3, 2017, 12:58pm UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/7 "2017-07-03T12:58:06Z")

</div>

I meant the method you get with e.g. `@less broadcast!(*, [1], 1, [1])`, and the methods which are called from there.

---

<div class="post-metadata">

**Author:** ![gasagna](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gasagna/32/1275_2.png) [@gasagna](https://discourse.julialang.org/u/gasagna)\
**Post date:** [July 3, 2017, 1:56pm UTC](https://discourse.julialang.org/t/allocation-using-broadcasting-with-custom-type/4592/8 "2017-07-03T13:56:55Z")

</div>

Ok. But adding inline annotations do not seem to be the cure.
