Struct variables explicit setting

FYI, I tested:
Vector{StaticArrays.SVector{3,Int}}
vs
Vector{Union{ StaticArrays.SVector{3,Int},StaticArrays.SVector{4,Int} }}
or
Array{SArray{S,Int64,1,L} where L where S<:Tuple,1}
and the first is by far the best (though not flexible), the second is 20-30% slower, and the third is 2x slower! I may need to look into TypeSortedCollections.
Thanks!

1 Like

Ok, I need one more tip:
when I first build my struct I will have a certain number N that will be defined then and won’t change.
I noticed that declaring StaticArrays with unknown numbers of elements is no good. Is there some way to have that number in the definition so the compiler treats it as hard coded?
Right now, I’m declaring my vectors like this:

a :: Vector{StaticArrays.SVector{L,StaticArrays.SVector{4,Int}} where L}
b :: Vector{StaticArrays.MArray{L,Float64} where L}

and again, I will know L at struct creation time.
Thanks!

You can parameterize your struct by N, see Types · The Julia Language

But, if N is too great or variable, it may be better to instead just use Core.Vector instead of StaticArrays.

1 Like

So that would look like this:

struct whatever{L}
a :: Vector{StaticArrays.SVector{L,StaticArrays.SVector{4,Int}}}
b :: Vector{StaticArrays.MArray{L,Float64}}
end

but this

a=whatever([SA[SA[1,2,3,4],SA[2,3,4,5]]],[MVector(1.2,2.2)])

does not work.

Also, do I have to declare my functions as fun(whatev{N}), to get good performance?
Oh, and how do I declare a regular Vector? I tried

c::Vector{L,Float64} # and {Float64,L}

but that did not work.
Thanks a lot!

In b, your declaration of an StaticArrays.MArray type is wrong, the REPL says the first argument should be a Tuple type instead of an Int value. Take a look at the StaticArrays documentation.

Also, do I have to declare my functions as fun(whatev{N}), to get good performance?

See this section of the performance tips and the surrounding sections:
https://docs.julialang.org/en/v1.7-dev/manual/performance-tips/#Type-declarations

Regarding Vectors, see
Multi-dimensional Arrays · The Julia Language. The gist of it is that Vectors are defined to be Arrays with only one dimension, and they do not take a length parameter. So use Vector{Float64}.

Ok, but this here doesn’t work either:

struct whatever{L}
  a :: Vector{StaticArrays.SVector{L,StaticArrays.SVector{4,Int}}}
  b :: Vector{StaticArrays.MArray{Tuple{L},Float64}}
end
a=whatever([SA[SA[1,2,3,4],SA[2,3,4,5]]],[MVector(1.2,2.2)])
ERROR: MethodError: no method matching whatever(::Array{SArray{Tuple{2},SArray{Tuple{4},Int64,1,4},1,2},1}, ::Array{MArray{Tuple{2},Float64,1,2},1})
Closest candidates are:
  whatever(::Array{SArray{Tuple{L},SArray{Tuple{4},Int64,1,4},1,L},1}, ::Array{MArray{Tuple{L},Float64,N,L1} where L1 where N,1}) where L at REPL[4]:2
Stacktrace:
 [1] top-level scope at REPL[5]:1

The performance tips don’t really mention using {N} when calling or declaring functions and I guess my vars are all super type safe, so I guess I’m good from that perspective.

Oh, so I can’t declare the length of Vectors. Thought it might help performance, but ok, then!
Thanks again!

This is the case for static arrays. It is important when the vectors are small, in particular, because they can be manipulated in the stack or processor registry. When they are large they go to the heap and that does not make sense anymore.

This a vector of static vectors of static vectors (three levels of vector nested). Are you sure that is what you want?

Also, you can be more relaxed about type signatures. For example:

struct Whatever{T1,T2}
  a :: Vector{T1}
  b :: T2
end
Whatever(x::Vector{T1},y::T2) where {T1,T2} = Whatever{T1,T2}(x,y)
julia> Whatever( [ SA[1,2], SA[3,4] ], MVector(1.0,2.0) )
Whatever{SArray{Tuple{2},Int64,1,2},MArray{Tuple{2},Float64,1,2}}(SArray{Tuple{2},Int64,1,2}[[1, 2], [
3, 4]], [1.0, 2.0])

The instance of Whatever created here is completely signed with the type of element of vector a and the static mutable type and size of b. That will allow dispatch and specialization for these types. This specialization results from what was given to Whatever on construction of the instance, not on the definition of the Whatever struct. A great advantage of this approach is that you can use and test your code with many different types of variables in those fields without having to redefine your structs. (this is one of the reasons of the great composability of Julia code).

Edited according to @rdeits note

2 Likes

This is not recommended for performance, see: Performance Tips · The Julia Language

2 Likes

Can anyone telll me how to do the Vector of MArrays? I still struggle a lot with these declarations.
Thanks!

You can use MVector{N, T} instead. The MVector type is just a convenient alias designed to make it easier to specify an MArray type by hand, which is exactly what you’re trying to do:

julia> MVector{3, Float64}
MArray{Tuple{3},Float64,1,3}

julia> v = Vector{MVector{3, Float64}}();

julia> push!(v, MVector(1, 2, 3))
1-element Array{MArray{Tuple{3},Float64,1,3},1}:
 [1.0, 2.0, 3.0]
2 Likes

@rdeits Ah, ok! I had tried that before, but I had messed up some other stuff.
This works:

using StaticArrays
struct whatever{L}
  a :: Vector{StaticArrays.SVector{L,StaticArrays.SVector{4,Int}}}
  b :: Vector{StaticArrays.MVector{L,Float64}}
end
a=whatever([SA[SA[1,2,3,4],SA[2,3,4,5]]],[MVector(1.2,2.2)])

Thanks a lot!