How to construct StaticArray?

Hi everyone. This is maybe a basic question regarding StaticArray.jl.

I had just started to use StaticArrays.jl to optimize some codes of mine.
I want to construct the SVector from Vector{SVector} like below

a = [@SVector rand(3) for _  in 1:500]
b = getindex.(a, 1) ## want to convert this to SVector

how can I do this in the simplest way?

You should not do it. StaticArrays is only for small arrays whose size are known at compile time. Maybe up to 100 elements. So they are great for length-3 vectors, for example, but not for length-500.

If your vector a were much shorter, you could do it, but not if it’s length is ‘dynamical’.

1 Like

Thank you for your suggestion.
Actually, my vector a is much shorter, and I want to use StaticArray, but I could not figure out what you mean by

you could do it, but not if it’s length is ‘dynamical’.

Could you tell me more details?

The performance advantage of SVectors come from that the compiler knowns the length of it, and can generate specialized code for that particular length. Then the length must be known by the compiler.

A Vector can have any length, and the compiler has no way of knowing how long it is. So you must tell the compiler how long a is for this to work well. So if you know that the length of a will be exactly 10 (for example) each time, you can write:

b = @SVector [a[i][1] for i in 1:10]

and it will be fast.

If you don’t know the length in advance, there are some tricks (involving function barriers and Val and such) which you can use to make it work, but the basic situation is that you should know the length beforehand, and let the compiler know.

1 Like

Static arrays are (short) arrays whose length is known at compile time. In your case the vector a is a normal array of static arrays. Normal arrays can have elements added to them or removed at any point, so they are dynamically sized. Therefore the compiler cannot figure out their length.
You can still construct a static array from values known at compile time by using the value dispatch Val (see the documentation), but this comes at the cost of runtime dispatch and should not be done at performance- critical sections of code. Although its said that static arrays are fine for up to 100 values, I think if your array is on this kind of scale you are better off using a standard array.

I think it would help to be more specific know what exactly you are optimizing here, XY problem - Wikipedia

1 Like

Here’s something a little more flexible:

foo(a, n, ::Val{N}) where {N} = SVector{N}(a[i][n] for i in 1:N)
# or, for general indexing:
foo(a, n, ::Val{N}) where {N} = SVector{N}(a[i][n] for i in firstindex(a).+(0:N-1))

It picks the nth value from each element vector. The length of the output vector is a type parameter, so it’s a bit more flexible, but you must still communicate the output length through the type system, using Val:

julia> foo(a, 2, Val(10))
10-element SVector{10, Float64} with indices SOneTo(10):
 0.5892927478216248
 0.5184612846127328
 0.028037283578832506
 0.6722261222139212
 0.19240186938036719
 0.22620922240970398
 0.7744478087741308
 0.9778164487539746
 0.5852152575385813
 0.3071161388424076

julia> foo(a, 3, Val(4))
4-element SVector{4, Float64} with indices SOneTo(4):
 0.940582486927162
 0.3906725410269195
 0.36708106216594005
 0.1063117662446108
1 Like

Thank you so much!
I understand your explanation. Actually in my case, I know the length in advance, so your suggestion completely solved the problem.
Thanks again!