Type stability question

question

#1

I don’t quite understand the type instability in the following MWE.

julia> function foo(A::AbstractArray{T, 2}) where T
           w = Int(sqrt(size(A, 1)))
           n = size(A, 3)
           A = reshape(A, w, w, n)
       end
foo (generic function with 1 method)

julia> x = rand(100, 4);

julia> @code_warntype foo(x)
Variables:
  #self# <optimized out>
  A@_2::Array{Float64,2}
  w::Int64
  n::Int64
  A@_5::Any

Body:
  begin 
      A@_5::Any = A@_2::Array{Float64,2}
      SSAValue(1) = (Base.arraysize)(A@_5::Array{Float64,2}, 1)::Int64
      SSAValue(2) = (Base.Math.sqrt_llvm)((Base.sitofp)(Float64, SSAValue(1))::Float64)::Float64
      w::Int64 = $(Expr(:invoke, MethodInstance for convert(::Type{Int64}, ::Float64), :(Base.convert), Int64, SSAValue(2))) # line 3:
      n::Int64 = (Base.arraysize)(A@_5::Array{Float64,2}, 3)::Int64 # line 4:
      SSAValue(0) = $(Expr(:invoke, MethodInstance for reshape(::Array{Float64,2}, ::Tuple{Int64,Int64,Int64}), :(Base.reshape), :(A@_5::Array{Float64,2}), :((Core.tuple)(w, w, n)::Tuple{Int64,Int64,Int64})))
      A@_5::Any = SSAValue(0)
      return SSAValue(0)
  end::Array{Float64,3}

Why the type of A is Any? Thanks!


#2

This type instability is nothing to worry about. Anywhere A@_5 is used it is inferred. Also, in 0.7 the list is:

julia> @code_warntype foo(x)
Variables:
  A@_2::Array{Float64,2}
  w<optimized out>
  n<optimized out>
  #temp#@_6::Bool
  #temp#@_7::Bool
  A@_9::Array{Float64,2}

#3

Thanks! This solved my question.


#4

In general, it’s not a good idea to do this, since Int(x) will error if x is not exactly equal to an Int, e.g. Int(sqrt(100)) will work, but Int(sqrt(10)) will error. In your particular case, it’s not catastrophic, since the reshape operation will also fail exactly when the Int() call fails, but still.

It’s safer to use isqrt(x) or round(Int, sqrt(x)) (or floor/ceil).


#5

BTW. There’s something wrong with your code. This line

n = size(A, 3)

should be

n = size(A, 2)

I think.


#6

Yes. You are right. In my real code, I am sure it has an integer square root. But using isqrt() probably is a good idea.


#7

You are right. That was a typo. Thanks!