When to use StaticArrays

I have been looking into StaticArrays.jl to speed up linear algebra but I think I am doing something wrong or testing the wrong things.

My first test was a simple linear model:

using StaticArrays, Random, BenchmarkTools
Random.seed!(123);
N = 100
p = 10
βtrue = 10 .* rand(p);
_X = rand(N, p);
_y = _X * βtrue + randn(N);

X = SMatrix{N, p}(_X);
y = SVector{N}(_y);
βstore = MVector{p}(zeros(p));

function lm!(X, y, b)
    b[:] = X\y
end

@btime lm!(X, y, βstore)

_βstore = zeros(p);
@btime lm!(_X, _y, _βstore)

But it looks like the version with regular arrays leads to fewer allocations and is faster:

julia> @btime lm!(X, y, βstore);
  11.318 μs (87 allocations: 94.55 KiB)

julia> @btime lm!(_X, _y, _βstore);
  10.734 μs (85 allocations: 86.52 KiB)

So my question is when to use StaticArrays and whether I am doing something wrong here?

The README of StaticArrays.jl says:
A very rough rule of thumb is that you should consider using a normal Array for arrays larger than 100 elements.

Your array X has already 1000 elements.

4 Likes

Note that b[:] = X\y will still allocate, you probably want to use lmul! here instead. For StaticArrays there’s also really no need to write this as a mutating function, you can just return X\y. Of course @ufechner7’s point still applies, I don’t expect any benefit from using StaticArrays for arrays this large.

1 Like

Thanks! I misread that as just applying to compile time. I get the best performance if I use MVector only for the parameters since they are quite low dimensional.

julia> @btime lm!(_X, _y, βstore);
  10.336 μs (85 allocations: 86.52 KiB)

julia> @btime lm!(_X, _y, _βstore);
  11.391 μs (85 allocations: 86.52 KiB)

I eventually plan to use this in MCMC so I’m overwriting the parameters quite often. This was just meant as a minimal example :slight_smile: I’ll test with some more realistic examples. Thanks for the help!