Type stability and array of matrices


#1

I am having some trouble getting a deeper understanding of inference / type stability. I have a struct with an array of matrices and a function. I want to extract something from a matrix in the array, say the size of the first matrix:

type MyType
   A::Array{<:AbstractArray,1}
end 
function firstsize(b::MyType); return size(b.A[1]); end
a=MyType([randn(3,3),randn(3,3)]);
firstsize(a)   
# gives (3,3)

If I run code_warntype on this I get:

 @code_warntype(firstsize(a))
Variables:
  #self# <optimized out>
  b::MyType

Body:
  begin 
      return (Main.size)((Base.arrayref)((Core.getfield)(b::MyType, :A)::Array{#s231,1} where #s231<:AbstractArray, 1)::AbstractArray)::Any
  end::Any

This function will be called many times in an inner loop. Should I worry about the ::Any as a return type? Why do I get ::Any and not Tuple{Int64,Int64}? Is there a way to get around it? I would preferable have the work for both sparse and dense matrices.


#2

https://docs.julialang.org/en/latest/manual/performance-tips/#Avoid-fields-with-abstract-type-1


#3

Use:

type MyType{T<:AbstractArray}
   A::Array{T,1}
end

and as long as A has homogenous type you will have full type stability.

Probably you also should change type to struct or mutable struct as type is deprecated.


#4

Great. Thanks for the extremely quick response and link. It seems to work. After reading the documentation still I have difficulties seeing the difference between MyType2 and MyType3:

julia> struct MyType1
          A::Array{AbstractArray,1}
       end
julia> struct MyType2
          A::Array{<:AbstractArray,1}
       end
julia> struct MyType3{T<:AbstractArray}
          A::Array{T,1}
       end

#5

In MyType3 you fix T and then all of the elements in A must be of the same type (T). In MyType2 it is enough that all of the elements in A or <:AbstractArray but they do not all have to be of the same type.


#6

Ah! Great. Thanks!