Types 有人能指出我代码中的类型不稳定吗?
我正在使用库进行一些区间计算,并试图优化我的代码。我定义如下:Types 有人能指出我代码中的类型不稳定吗?,types,julia,Types,Julia,我正在使用库进行一些区间计算,并试图优化我的代码。我定义如下: using ValidatedNumerics immutable Vector2D{T} x::Complex{ValidatedNumerics.Interval{T}} y::Complex{ValidatedNumerics.Interval{T}} end function F(x::Complex{ValidatedNumerics.Interval{BigFloat}},y::Complex{Validat
using ValidatedNumerics
immutable Vector2D{T}
x::Complex{ValidatedNumerics.Interval{T}}
y::Complex{ValidatedNumerics.Interval{T}}
end
function F(x::Complex{ValidatedNumerics.Interval{BigFloat}},y::Complex{ValidatedNumerics.Interval{BigFloat}})
g = 3(1+(1+x+y)^2)/4
Vector2D{BigFloat}(x + 2y + g,y + g)
end
然后使用以下命令给出正确的答案
x = @biginterval(1+1im)
F(x,x)
但是,当我键入时:
@code_warntype F(x,x)
我得到:
Variables:
#self#::#F
x::Complex{ValidatedNumerics.Interval{BigFloat}}
y::Complex{ValidatedNumerics.Interval{BigFloat}}
g::Complex{T<:Real}
Body:
begin
# meta: location operators.jl + 138
# meta: location complex.jl + 162
SSAValue(0) = (Core.getfield)(x::Complex{ValidatedNumerics.Interval{BigFloat}},:re)::ValidatedNumerics.Interval{BigFloat}
SSAValue(2) = $(Expr(:invoke, LambdaInfo for +(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.+), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for _convert_rounding(::Type{BigFloat}, ::Int64, ::RoundingMode{:Down}), :(Base.Rounding._convert_rounding), BigFloat, 1, :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for _convert_rounding(::Type{BigFloat}, ::Int64, ::RoundingMode{:Up}), :(Base.Rounding._convert_rounding), BigFloat, 1, :(ValidatedNumerics.RoundUp))))))), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(0),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(0),:hi)::BigFloat), :(ValidatedNumerics.RoundUp)))))))))
SSAValue(1) = (Core.getfield)(x::Complex{ValidatedNumerics.Interval{BigFloat}},:im)::ValidatedNumerics.Interval{BigFloat}
# meta: pop location
SSAValue(7) = $(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(2),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(2),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))
SSAValue(8) = $(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(1),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(1),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))
# meta: location complex.jl + 125
SSAValue(5) = $(Expr(:invoke, LambdaInfo for +(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.+), SSAValue(7), :((Core.getfield)(y,:re)::ValidatedNumerics.Interval{BigFloat})))
SSAValue(4) = $(Expr(:invoke, LambdaInfo for +(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.+), SSAValue(8), :((Core.getfield)(y,:im)::ValidatedNumerics.Interval{BigFloat})))
# meta: pop location
SSAValue(6) = $(Expr(:new, Complex{ValidatedNumerics.Interval{BigFloat}}, :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(5),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(5),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(4),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(4),:hi)::BigFloat), :(ValidatedNumerics.RoundUp)))))))))
# meta: pop location
SSAValue(9) = (3 * (1 + (Core._apply)(Base.^,$(Expr(:invoke, LambdaInfo for promote(::Complex{ValidatedNumerics.Interval{BigFloat}}, ::Complex{Int64}), :(Base.promote), SSAValue(6), :($(Expr(:new, Complex{Int64}, 2, 0))))))::Complex{T<:Real})::Complex{T<:Real})::Complex{T<:Real}
g::Complex{T<:Real} = (Base.Complex)(((Core.getfield)(SSAValue(9),:re)::Real / 4)::Any,((Core.getfield)(SSAValue(9),:im)::Real / 4)::Any)::Complex{T<:Real} # line 3:
# meta: location complex.jl * 170
SSAValue(11) = (Core.getfield)(y::Complex{ValidatedNumerics.Interval{BigFloat}},:re)::ValidatedNumerics.Interval{BigFloat}
SSAValue(12) = $(Expr(:invoke, LambdaInfo for *(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.*), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for _convert_rounding(::Type{BigFloat}, ::Int64, ::RoundingMode{:Down}), :(Base.Rounding._convert_rounding), BigFloat, 2, :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for _convert_rounding(::Type{BigFloat}, ::Int64, ::RoundingMode{:Up}), :(Base.Rounding._convert_rounding), BigFloat, 2, :(ValidatedNumerics.RoundUp))))))), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(11),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(11),:hi)::BigFloat), :(ValidatedNumerics.RoundUp)))))))))
SSAValue(10) = (Core.getfield)(y::Complex{ValidatedNumerics.Interval{BigFloat}},:im)::ValidatedNumerics.Interval{BigFloat}
SSAValue(13) = $(Expr(:invoke, LambdaInfo for *(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.*), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for _convert_rounding(::Type{BigFloat}, ::Int64, ::RoundingMode{:Down}), :(Base.Rounding._convert_rounding), BigFloat, 2, :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for _convert_rounding(::Type{BigFloat}, ::Int64, ::RoundingMode{:Up}), :(Base.Rounding._convert_rounding), BigFloat, 2, :(ValidatedNumerics.RoundUp))))))), :($(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(10),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(10),:hi)::BigFloat), :(ValidatedNumerics.RoundUp)))))))))
# meta: pop location
SSAValue(22) = $(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(12),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(12),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))
SSAValue(23) = $(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(13),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(13),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))
# meta: location operators.jl + 138
# meta: location complex.jl + 125
SSAValue(16) = $(Expr(:invoke, LambdaInfo for +(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.+), :((Core.getfield)(x,:re)::ValidatedNumerics.Interval{BigFloat}), SSAValue(22)))
SSAValue(15) = $(Expr(:invoke, LambdaInfo for +(::ValidatedNumerics.Interval{BigFloat}, ::ValidatedNumerics.Interval{BigFloat}), :(Base.+), :((Core.getfield)(x,:im)::ValidatedNumerics.Interval{BigFloat}), SSAValue(23)))
# meta: pop location
SSAValue(19) = $(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(16),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(16),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))
SSAValue(20) = $(Expr(:invoke, LambdaInfo for ValidatedNumerics.Interval{BigFloat}(::BigFloat, ::BigFloat), ValidatedNumerics.Interval{BigFloat}, :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Down}), BigFloat, :((Core.getfield)(SSAValue(15),:lo)::BigFloat), :(ValidatedNumerics.RoundDown)))), :($(Expr(:invoke, LambdaInfo for BigFloat(::BigFloat, ::RoundingMode{:Up}), BigFloat, :((Core.getfield)(SSAValue(15),:hi)::BigFloat), :(ValidatedNumerics.RoundUp))))))
SSAValue(18) = (Base.Complex)((SSAValue(19) + (Core.getfield)(g::Complex{T<:Real},:re)::Real)::Any,(SSAValue(20) + (Core.getfield)(g::Complex{T<:Real},:im)::Real)::Any)::Complex{T<:Real}
# meta: pop location
SSAValue(21) = (Base.Complex)(((Core.getfield)(y::Complex{ValidatedNumerics.Interval{BigFloat}},:re)::ValidatedNumerics.Interval{BigFloat} + (Core.getfield)(g::Complex{T<:Real},:re)::Real)::Any,((Core.getfield)(y::Complex{ValidatedNumerics.Interval{BigFloat}},:im)::ValidatedNumerics.Interval{BigFloat} + (Core.getfield)(g::Complex{T<:Real},:im)::Real)::Any)::Complex{T<:Real}
return $(Expr(:new, Vector2D{BigFloat}, :($(Expr(:new, Complex{ValidatedNumerics.Interval{BigFloat}}, :((Base.convert)(ValidatedNumerics.Interval{BigFloat},(Core.getfield)(SSAValue(18),:re)::Real)), :((Base.convert)(ValidatedNumerics.Interval{BigFloat},(Core.getfield)(SSAValue(18),:im)::Real))))), :($(Expr(:new, Complex{ValidatedNumerics.Interval{BigFloat}}, :((Base.convert)(ValidatedNumerics.Interval{BigFloat},(Core.getfield)(SSAValue(21),:re)::Real)), :((Base.convert)(ValidatedNumerics.Interval{BigFloat},(Core.getfield)(SSAValue(21),:im)::Real)))))))
end::Vector2D{BigFloat}
变量:
#赛尔夫
x::复数{ValidatedNumerics.Interval{BigFloat}
y::复数{ValidatedNumerics.Interval{BigFloat}
g::复杂{T正如@David Sanders所指出的SSAValue(9)
是F
问题的根源。进一步挖掘(后面有相当多的挖掘),是^2
扰乱了类型推断。到^
的参数的类型签名是
Complex{ValidatedNumerics.Interval{BigFloat}}, Int64
在将2
转换为Complex{Int64}(2,0)
后,调用^(Complex,Complex)
。反过来,^(Complex,Complex)
将Complex{Int64}
提升为Complex{ValidatedNumerics.Interval{BigFloat}
。现在,我们开始在中进行一些实际计算^(我不确定这里发生了什么;似乎有一些事情朱莉娅搞不清楚(如果你在REPL中检查,似乎是在SSA(9)
中的促销中,那里有不稳定计算类型的颜色突出显示)。但是我认为,与任何情况下操纵BigFloat
Interval
s的运行时间相比,类型不稳定性带来的时间损失都很小!类型不稳定性只在您希望提高性能时才起作用,而这实际上是运行时间的一个重要部分。请注意,您可以只编写s>Interval
,而不是ValidatedNumerics.Interval
。您也可以参数化函数F
,而不是使用显式类型。我正在尝试参数化F,但我不太确定如何处理复数。我希望复数是实数的超类型,但事实并非如此。我正在阅读相关文章。谢谢您r reply@tst您需要做如下操作:F{TI通过设置g=3(1+(1+x+y)*(1+x+y))/4这似乎解决了我的问题,我现在没有得到任何红色,所以我假设它是固定的。对吗?julia中的Complex当前被实现为对相同类型的值(必须是Real的子类型)的“包装器”。这样就可以根据所需的精度和实数实现灵活地插入不同版本的实数,并且仍然可以得到正确的复数运算。您的示例证明了Interval作为插件是有效的。这实际上是julia语言优势的一个很好的示例。生成高效的ean代码,即使它结合了来自不同来源的包。这是相当多的侦探工作@Dan,谢谢!我会在有时间的时候看看修改源代码。好的,显然我误解了。问题实际上在复杂。jl
在base Julia?我要在那里打开一个问题吗?
Complex{ValidatedNumerics.Interval{BigFloat}}, Int64
function ^{T<:Complex}(z::T, p::T)
if isinteger(p)
rp = real(p) # <---------- (1)
if rp < 0
return power_by_squaring(inv(float(z)), convert(Integer, -rp))
else
return power_by_squaring(float(z), convert(Integer, rp))
end
end
pr, pim = reim(p)
zr, zi = reim(z)
r = abs(z) # <---------- (*)
rp = r^pr # <---------- (2)
theta = atan2(zi, zr)
sqrt(z::Complex) = sqrt(float(z))