I am transitioning quantum chemistry code from Matlab to Julia 0.5.0. Great experience so far!
I am having trouble with type instability in one of the performance-critical functions. The function is recursive and involves 6 recursion relationships with 6 terms each. When terminating the recursion, it returns values that are pre-computed outside the recursion function.
Here is a minimal example (boiled down to one recursion relation with a single term, and no math) that shows the same type inference behavior:
function outerfun0()
val = 1.0 # expensive to calculate
function recur(a)
if a>0
return recur(a-1)
else
return val
end
end
@code_warntype recur(2)
end
The output is
Variables:
#self#::#recur#25{Float64}
a::Int64
Body:
begin
unless (Base.slt_int)(0,a::Int64)::Bool goto 4 # line 8:
return ((Core.getfield)((Core.getfield)(#self#::#recur#25{Float64},:recur)::CORE.BOX,:contents)::ANY)((Base.box)(Int64,(Base.sub_int)(a::Int64,1)))::ANY
4: # line 10:
return (Core.getfield)(#self#::#recur#25{Float64},:val)::Float64
end::ANY
I do not understand why there is ::ANY
and ::CORE.BOX
, which I think indicate a type instability related to the return type of recur
. Julia seems to correctly infer types for a
(Int64
) and for val
(Float64
). All the code paths through recur
return a Float64
. So everything appears to be type-stable.
Interestingly, if I remove val
in the inner function, the ::CORE.BOX
disappears, but ::ANY
stays:
function outerfun1()
val = 1.0 # expensive to calculate
function recur(a)
if a>0
return recur(a-1)
else
return 1.0
end
end
@code_warntype recur(2)
end
Output:
Variables:
#self#::#recur#30
a::Int64
Body:
begin
unless (Base.slt_int)(0,a::Int64)::Bool goto 4 # line 24:
return ((Core.getfield)((Core.getfield)(#self#::#recur#30,:recur)::ANY,:contents)::ANY)((Base.box)(Int64,(Base.sub_int)(a::Int64,1)))::ANY
4: # line 26:
return 1.0
end::ANY
How to get rid of this type instability? I can’t find a way. Neither type-annotating the return type of ‘recur’ nor wrapping both return expressions of recur
with Float64()
appears to help.