Hi all,
I have been having problems making my functions type stable as I don’t entirely understand how it works.
I managed to make most of my functions type stable (I think) but I am having problems with the most performance sensitive one. I believe the problem has to do with the fact that I decided to use multiple dispatch and one of the outputs is an array with different size depending on what type it is fed with.
I tried to build a minimal working example of my problem. In my code I am doing more complicated things in the iterator
function, calling all sorts of other user-defined functions, but I do have a max
operator in there and I believe that’s where the problems start.
Here’s the MWE:
abstract type Agent end
abstract type Entr <: Agent end
abstract type Work <: Agent end
immutable Ye <: Entr end
immutable Yw <: Work end
immutable Oe <: Entr end
immutable Ow <: Work end
mutable struct Dimensions
x_dim::Int64
y_dim::Int64
z_dim::Int64
end
mutable struct Household
h_type::Agent
dim::Dimensions
V::Array{Float64,N} where {N}
pol_tuple::NTuple{N,Array{Float64}} where {N}
end
function Dimensions()
x_dim = 10; y_dim = 2; z_dim = 2
return Dimensions(x_dim,y_dim,z_dim)
end
D = Dimensions()
function Household( h_type::Agent;
dim::Dimensions = D)
function initiate(h_type::Ye)
V = zeros(Float64,dim.x_dim,dim.y_dim,dim.z_dim)
a = zeros(Float64,dim.x_dim,dim.y_dim,dim.z_dim)
c = zeros(Float64,dim.x_dim,dim.y_dim,dim.z_dim)
return V::Array{Float64,3}, (a,c)
end
function initiate(h_type::Yw)
V = ones(Float64,dim.x_dim,dim.y_dim)
k = ones(Float64,dim.x_dim,dim.y_dim)
c = ones(Float64,dim.x_dim,dim.y_dim)
return V::Array{Float64,2}, (k,c)
end
(V, pol_tuple) = initiate(h_type)
return Household(h_type,dim,V,pol_tuple)
end
function iterator!(hs::NTuple{N,Household} where {N})
(hye,hyw) = hs
Vye = similar(hye.V::Array{Float64,3})
Vyw = similar(hyw.V::Array{Float64,2})
Vye = max.(2.0*rand(hye.dim.x_dim,hye.dim.y_dim,hye.dim.y_dim)-1.0,hye.V::Array{Float64,3})
Vyw = max.(2.0*rand(hye.dim.x_dim,hye.dim.y_dim),hyw.V::Array{Float64,2})
hye.V::Array{Float64,3} = Vye::Array{Float64,3}
hyw.V::Array{Float64,2} = Vyw::Array{Float64,2}
end
hye = Household(Ye())
hyw = Household(Yw())
iterator!((hye,hyw))
Looking at the output of @code_warntype
I see many issues, the biggest of which seems to be that, when it tries to get the :V
field of either hyw
or hye
, it does not know what’s its size.
I suspect the problem here is that both are the outcome of the initiate function, which outputs differently sized arrays depending on whether the type is ::Yw
or ::Ye
.
Also, if you have any sorts of general performance suggestions they are very well appreciated!
Thanks a lot in advance.