# Jacobian of StaticArray function becoming type-unstable

**URL:** <https://discourse.julialang.org/t/jacobian-of-staticarray-function-becoming-type-unstable/19045>\
**Category:** Performance\
**Created:** [December 27, 2018, 11:38pm UTC](https://discourse.julialang.org/t/jacobian-of-staticarray-function-becoming-type-unstable/19045 "2018-12-27T23:38:08Z")\
**Posts on this page:** 4\
**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:** [December 27, 2018, 11:38pm UTC](https://discourse.julialang.org/t/jacobian-of-staticarray-function-becoming-type-unstable/19045/1 "2018-12-27T23:38:08Z")

</div>

I’m trying to remove allocations from this optimization code where I’m using ForwardDiff to calculate a Jacobian matrix, and I seem to have found some corner case where the Jacobian becomes type-unstable even though each individual gradient is fine. Any hints? Possible bug?

And a philosophical question: how do I locate the piece of code that needs to change? Can the type system turn that into an error?

```julia
using ForwardDiff
using StaticArrays
using LinearAlgebra
using BenchmarkTools

function fa(w)
    t = norm(w)
    if t == 0
        @SVector [1.0, 0, 0]
    else
        (@SVector [w[1], -w[2], w[3]]) / t
    end
end

function fb(w)
    t = norm(w)
    (@SVector [w[1], -w[2], w[3]]) / t
end
julia> pp = (@SVector [0.2, -0.1, 0.1]);

julia> @btime ForwardDiff.jacobian(fa, $pp);
  108.554 ns (3 allocations: 224 bytes)

julia> @btime ForwardDiff.jacobian(fb, $pp);
  31.271 ns (0 allocations: 0 bytes)

julia> @btime ForwardDiff.gradient(x->fa(x)[1], $pp);
  45.366 ns (0 allocations: 0 bytes)

julia> @btime ForwardDiff.gradient(x->fb(x)[1], $pp);
  32.817 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 27, 2018, 11:58pm UTC](https://discourse.julialang.org/t/jacobian-of-staticarray-function-becoming-type-unstable/19045/2 "2018-12-27T23:58:48Z")

</div>

Because your input function is type unstable (check `@code_warntype ForwardDiff.jacobian(fa, pp)`).

```julia
julia> function fa(w::AbstractVector{T}) where {T}
           t = norm(w)
           if t == 0
               (@SVector [1.0, 0, 0]) * one(T)
           else
               (@SVector [w[1], -w[2], w[3]]) / t
           end
       end

julia> @btime ForwardDiff.jacobian(fa, $pp);
  66.138 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 28, 2018, 7:02am UTC](https://discourse.julialang.org/t/jacobian-of-staticarray-function-becoming-type-unstable/19045/3 "2018-12-28T07:02:41Z")

</div>

In addition to what @kristoffer.carlsson suggested, you can configure the chunk size, see

[http://www.juliadiff.org/ForwardDiff.jl/stable/user/advanced.html#Configuring-Chunk-Size-1](http://www.juliadiff.org/ForwardDiff.jl/stable/user/advanced.html#Configuring-Chunk-Size-1)

as that is usually the type unstable part.

---

<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:** [December 28, 2018, 9:44am UTC](https://discourse.julialang.org/t/jacobian-of-staticarray-function-becoming-type-unstable/19045/4 "2018-12-28T09:44:16Z")

</div>

All right! Sorry, I thought I had checked that, now I’ve seen the light!
