# Broadcasting call to a vector-valued function

**URL:** <https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056>\
**Category:** Performance\
**Tags:** broadcast\
**Created:** [November 11, 2023, 12:16am UTC](https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056 "2023-11-11T00:16:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)\
**Post date:** [November 11, 2023, 12:16am UTC](https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056/1 "2023-11-11T00:16:25Z")

</div>

What is the most julian way to broadcast a call to a vector-valued function?

For example, take the following function.

```julia
function return_vec(x)
    return [x, x^2]
end

```

I would like to collect outputs for each `x` in `1:15` and store the result in a 15x2 Matrix. I can do either of the following quickly:

```julia
julia> @btime hcat(return_vec.(1:15)...)';
  548.913 ns (22 allocations: 2.11 KiB)

julia> @btime hcat(map(return_vec,1:15)...)';
  563.187 ns (22 allocations: 2.11 KiB)

```

but somewhat inefficiently. Alternatively, I can define:

```julia
function manual_broadcast(X)
    out = zeros(eltype(X), length(X),2)
    for i in eachindex(X)
        out[i,:] .= return_vec(X[i])
    end
    return out
end

```

And get a 1.74x speedup:

```julia
julia> @btime manual_broadcast(1:15);
  316.522 ns (16 allocations: 1.47 KiB)

```

But is there any syntactic sugar that would effectively implement `manual_broadcast`? Surely this is common enough that I don’t need to write my own function to do it?

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [November 11, 2023, 12:26am UTC](https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056/2 "2023-11-11T00:26:14Z")

</div>

Does…

```julia
julia> function return_vec(x)
           return (x, x^2)
       end
return_vec (generic function with 1 method)

julia> @btime stack(return_vec.(1:15); dims=1);
  58.087 ns (2 allocations: 608 bytes)

```

… follow the requirements of the question? It’s pretty fast.

---

<div class="post-metadata">

**Author:** ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)\
**Post date:** [November 11, 2023, 12:30am UTC](https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056/4 "2023-11-11T00:30:01Z")

</div>

Yep, exactly what I was looking for. Thanks! Hadn’t heard of `stack` before.

But when I run it, I get

```julia
@btime stack(return_vec.(1:15); dims=1);
  306.410 ns (17 allocations: 1.64 KiB)

```

Why so many more allocations??

---

<div class="post-metadata">

**Author:** ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)\
**Post date:** [November 11, 2023, 12:31am UTC](https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056/5 "2023-11-11T00:31:56Z")

</div>

Figured it out. You changed the return to a tuple. Makes sense.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 11, 2023, 1:55am UTC](https://discourse.julialang.org/t/broadcasting-call-to-a-vector-valued-function/106056/6 "2023-11-11T01:55:38Z")

</div>

> [@Dan](#):
>
> `julia> @btime stack(return_vec.(1:15); dims=1);`

You can save a factor of 2 in time and memory by not allocating the temporary array from broadcasting, and instead pass `return_vec` as the first argument of `stack`:

```julia
julia> @btime stack(return_vec.(1:15); dims=1);
  96.559 ns (2 allocations: 608 bytes)

julia> @btime stack(return_vec, 1:15; dims=1);
  51.247 ns (1 allocation: 304 bytes)

```
