Creating random `MMatrix` with large size is too slow

I want to create a StaticArrays.MMatrix with a somewhat medium or large size using rand, but it seems much slower than the plain Matrix and it took a long time for it to display:

using StaticArray: MMatrix

N = 10
m = rand(N, N)

julia> @btime MMatrix{N,N}(m);
  1.067 μs (22 allocations: 1.89 KiB)

julia> @btime rand(N, N);
  136.503 ns (1 allocation: 896 bytes)

N = 40

julia> @btime m;
  2.125 ns (0 allocations: 0 bytes)

julia> @btime rand(N, N);
  1.179 μs (1 allocation: 12.62 KiB)

What should I do?

As it says in the README of StaticArrays.jl:

Note that in the current implementation, working with large StaticArrays puts a lot of stress on the compiler, and becomes slower than Base.Array as the size increases. A very rough rule of thumb is that you should consider using a normal Array for arrays larger than 100 elements.

Regarding

that depends entirely on what you’re trying to do. Do you really need static sizing here? Are you trying to stack allocate everything?

1 Like

Oh, thank you! I do not know that it has this limitation.

Do you really need static sizing here? Are you trying to stack allocate everything?

Not really, I rarely use MMatrix and thought they would be performant if I want to store them with fixed sizes.

I just want a performant Matrix and Array type. I do not know if the builtin types are enough.

Matrix is already fast.

If all you need is fixed size, note the existence of SizedArray (and SizedVector/SizedMatrix) within StaticArrays.jl, which lets you assign fixed dimensions to standard Julia arrays.

1 Like

While 40x40 is beyond the size where you really should be using a MMatrix, 10x10 is totally acceptable. What you’re seeing is a benchmarking artifact of global variables m and N.

using StaticArrays
using BenchmarkTools

N = 10;
m = rand(10, 10);

@btime rand(MMatrix{N,N}); # N is not a known constant so this performs badly
# 1.420 μs (22 allocations: 1.89 KiB)

@btime MMatrix{10,10}($m); # literals are fine
# 34.441 ns (1 allocation: 816 bytes)

const Nconst = 10
@btime MMatrix{Nconst,Nconst}($m); # const N is fine
# 33.972 ns (1 allocation: 816 bytes)

m = rand(40, 40);
@btime MMatrix{40,40}($m); # bigger than a MMatrix really should be
#  1.520 μs (1 allocation: 12.56 KiB)

Although, really, you should not generate random matrices this way. Use either of these equivalent methods:

julia> @btime @MMatrix rand(10,10);
  153.006 ns (1 allocation: 816 bytes)

julia> @btime rand(MMatrix{10,10});
  153.129 ns (1 allocation: 816 bytes)

I’ll reiterate that if the size of any StaticArrays array is not known at compile time, there is little benefit to using it over a normal Array unless it will be passed down into other functions where its size can be known.