Consider the following code:
using Random
mutable struct mystate{Tq}
x::AbstractArray{Tq,1}
end
function update!(state::mystate{Tq}) where Tq
@. state.x[1] = 0.5 * state.x[2] + randn();
@. state.x[2] = -0.5 * state.x[1] + randn();
state
end
function prep(x0::AbstractArray{Tq,1}) where Tq
state = mystate(x0);
return state
# return ar1(xdata, 100);
end
function integrate_path(x0::AbstractArray{Tq,1}, n_iters::Int) where Tq
state= prep(x0);
for j in 1:n_iters
update!(state)
end
return state.x
end
X0 = [[1.],[-2.]];
Random.seed!(100);
# ar1(x0,100)
@code_warntype integrate_path(X0, 100)
On my v1.4 installation, this generates a type instability:
Variables
#self#::Core.Compiler.Const(integrate_path, false)
x0::Array{Array{Float64,1},1}
n_iters::Int64
state::mystate{Array{Float64,1}}
@_5::Union{Nothing, Tuple{Int64,Int64}}
j::Int64
Body::AbstractArray{Array{Float64,1},1}
1 β (state = Main.prep(x0))
β %2 = (1:n_iters)::Core.Compiler.PartialStruct(UnitRange{Int64}, Any[Core.Compiler.Const(1, false), Int64])
β (@_5 = Base.iterate(%2))
β %4 = (@_5 === nothing)::Bool
β %5 = Base.not_int(%4)::Bool
βββ goto #4 if not %5
2 β %7 = @_5::Tuple{Int64,Int64}::Tuple{Int64,Int64}
β (j = Core.getfield(%7, 1))
β %9 = Core.getfield(%7, 2)::Int64
β Main.update!(state)
β (@_5 = Base.iterate(%2, %9))
β %12 = (@_5 === nothing)::Bool
β %13 = Base.not_int(%12)::Bool
βββ goto #4 if not %13
3 β goto #2
4 β %16 = Base.getproperty(state, :x)::AbstractArray{Array{Float64,1},1}
βββ return %16
where, in my terminal, the AbstractArray{Array{Float64,1},1}
appear in red (which I am interpreting as bad). If I switch to Array{Tq,1}
, the instability disappears. Questions:
- Is this red actually bad from either a style/perfomance point of view?
- What am I losing by just using
Array{Tq,1}
instead? The reason I had wanted it to be more general was so that the actual code I am using could handle things likeSharedArrays
. - Is there a way to avoid this type instability but maintain the flexibility of
AbstractArray
? - Any other recommendations?