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 StaticArray
s 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 I’ll test with some more realistic examples. Thanks for the help!