What is the best way to convert a larger array to a StaticArray. I have tried the following which works fine for a small array but not for a medium size.
using StaticArrays
# this works
A1 = zeros(UInt16, (3, 4, 5));
@time S1 = SArray{Tuple{3, 4, 5}, UInt16, 3, length(A1)}(A1);
# this hangs and does not finish in 10 min
A2 = zeros(UInt16, (64, 64, 30));
@time S2 = SArray{Tuple{64, 64, 30}, UInt16, 3, length(A2)}(A2)
Note that in the current implementation, working with large StaticArray s 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.
Thank you for the answer. I will have to refactor some code then. I liked to use the static arrays because I could have the size as part of the type but I will just find another way to handle it.
In case it’s relevant to your use case, it’s okay to have large Arrays of small-ish StaticArrays. For example, zeros(SVector{64, UInt16}, 64, 30) (i.e., a Matrix{<:SVector{64}}) is still within the usable size for SVector. A common example of this pattern is storing large sets of 3D coordinates as a Vector{SVector{3,Float64}}.
Although zeros(SMatrix{64, 64, UInt16}, 30) is too large a SMatrix to be useful, so this pattern only goes so far. It would probably compile in a mostly-usable amount of time, but its performance would be similar to or worse than a similarly-sized Matrix.
I was autogenerating structs for each record type and many of the fields are fixed sized Arrays. I was using StaticArrays for these fields so the record type contained all necessary information to read the record from disk.
Sized Array could be the answer for this. I will try it out. Alternatively I will just switch to regular arrays and pipe the array sizes around separately.
I have just tried SizedArray. It is easy to construct large SizedArrays but I quick run into compile issues again when I try to use the large SizedArrays. I am sure I can find workaround for many of the things but right now it is cleaner just to switch to regular Arrays. Here is a dummy example:
using StaticArrays
# Construction works fine now
A = zeros(UInt16, (10, 10, 10));
T = SizedArray{Tuple{size(A)...}, eltype(A), ndims(A), ndims(A), typeof(A)}
@time S = T(A);
S2 = T(copy(A));
# using the SizedArray uses a lot of compile time
@time all(S .== S2) # 8.2 seconds, 100 % compile time
@time all(A .== S2) # 13.12 seconds, 100 % compile time
I am reading several fixed sized array fields from a binary file format. Reading these fields I need to know that they are arrays, the element type and the size of the array. It was therefore convenient to have the size as part of the type.