# Can Julia Optimize an array expression?

**URL:** <https://discourse.julialang.org/t/can-julia-optimize-an-array-expression/18182>\
**Category:** Performance\
**Created:** [November 30, 2018, 1:36pm UTC](https://discourse.julialang.org/t/can-julia-optimize-an-array-expression/18182 "2018-11-30T13:36:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [November 30, 2018, 1:36pm UTC](https://discourse.julialang.org/t/can-julia-optimize-an-array-expression/18182/1 "2018-11-30T13:36:10Z")

</div>

Suppose I write a function that operates over (simple) arrays, even just taking floats as an input to construct the array, can Julia optimize the whole thing into a simple expression?

```julia
function f(a::Float64,b::Float64)
    [a b] * [a+1; b+1]
end

```

versus

```julia
function g(a::Float64, b::Float64)
    a * (a+1) + b * (b+1)
end

```

This gist shows an example  
[https://gist.github.com/nlw0/15636a55c560f62587042f82ca4b1e0e](https://gist.github.com/nlw0/15636a55c560f62587042f82ca4b1e0e)

Would it be necessary perhaps for me to use a more specialized matrix computation compiler library, for instance, or is this something we might see the Julia compiler do someday? Or is this something that might happen only in the JIT level, perhaps?

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [November 30, 2018, 1:48pm UTC](https://discourse.julialang.org/t/can-julia-optimize-an-array-expression/18182/2 "2018-11-30T13:48:41Z")

</div>

> can Julia optimize the whole thing into a simple expression?

No, but it works if you use static arrays

```julia
using StaticArrays, BenchmarkTools

function f(a,b)
    [a b] * [a+1; b+1]
end

function g(a,b)
    @SVector([a, b])' * @SVector([a+1, b+1])
end

julia> @btime f(3,4)
  74.892 ns (3 allocations: 288 bytes)
1-element Array{Int64,1}:
 32

julia> @btime g(3,4)
  1.266 ns (0 allocations: 0 bytes)
32

```

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [November 30, 2018, 2:12pm UTC](https://discourse.julialang.org/t/can-julia-optimize-an-array-expression/18182/3 "2018-11-30T14:12:38Z")

</div>

You can even use MVectors if the calls get inlined:

```julia
julia> using StaticArrays, BenchmarkTools

julia> function f(a,b)
           [a, b]' * [a+1, b+1]
       end
f (generic function with 1 method)

julia> function g(a,b)
           @SVector([a, b])' * @SVector([a+1, b+1])
       end
g (generic function with 1 method)

julia> function h(a,b)
           @MVector([a, b])' * @MVector([a+1, b+1])
       end
h (generic function with 1 method)

julia> @btime f(3,4)
  53.826 ns (2 allocations: 192 bytes)
32

julia> @btime g(3,4)
  0.020 ns (0 allocations: 0 bytes)
32

julia> @btime h(3,4)
  15.013 ns (3 allocations: 80 bytes)
32

julia> @inline function mdot(a::AbstractVector{T},b::AbstractVector{T}) where {T}
           out = zero(T)
           @inbounds for n ∈ eachindex(a,b)
               out += a[n] * b[n]
           end
           out
       end
mdot (generic function with 1 method)

julia> function h2(a,b)
           mdot(@MVector([a, b]), @MVector([a+1, b+1]))
       end
h2 (generic function with 1 method)

julia> @btime h2(3,4)
  2.725 ns (0 allocations: 0 bytes)
32

```

I would guess that the inline heuristics will eventually become smarter about figuring that out on their own.
