仍然有点困惑,要在Julia中使函数类型稳定。 这是我的功能
function tran7(C::Array{Float64,1}, flux_up::Float64, D::Array{Float64,1},
v::Array{Float64,1}, AFDW::Array{Float64,1}, VF::Array{Float64,1},
VF_mid::Array{Float64,1})
C_up = Float64[];
flux = Array{Float64,1}(N+1); dC = Array{Float64, 1}(N)
C_up = (flux_up + VF[1]*(D[1]/dx_aux[1] + (1-AFDW[1])*v[1])*C[1])/
(VF[1]*(D[1]/dx_aux[1] + AFDW[1]*v[1]))
flux = -VF.*D.*(vcat(C_up,C,C[N])[2:(N+2)] -
vcat(C_up,C,C[N])[1:(N+1)])./dx_aux +
VF.*v.*(AFDW.*vcat(C_up,C) + (1-AFDW).*vcat(C,C[N]))
flux[1] = flux_up
dC = -(flux[2:(N+1)] - flux[1:N])./(VF_mid.*dx)
return dC
end
这是@code_warntype结果
Variables:
#self# <optimized out>
C::Array{Float64,1}
flux_up::Float64
D::Array{Float64,1}
v::Array{Float64,1}
AFDW::Array{Float64,1}
VF::Array{Float64,1}
VF_mid::Array{Float64,1}
#200::##200#203
#201::##201#204
#202::##202#205
C_down <optimized out>
C_up::ANY
flux::ANY
dC::ANY
#temp#@_16::Core.MethodInstance
#temp#@_17::ANY
#temp#@_18::Core.MethodInstance
#temp#@_19::ANY
#temp#@_20 <optimized out>
Body:
begin
C_up::ANY = $(Expr(:foreigncall, :(:jl_alloc_array_1d),
Array{Float64,1}, svec(Any, Int64), Array{Float64,1}, 0, 0, 0)) # line 5:
$(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Float64,1}, svec(Any, Int64), Array{Float64,1}, 0, 0, 0)) # line 6:
flux::ANY = (Array{Float64,1})((Main.N + 1)::ANY)::Array{Float64,1} # line 6:
dC::ANY = (Array{Float64,1})(Main.N)::Array{Float64,1} # line 8:
SSAValue(21) = (Base.arrayref)(VF::Array{Float64,1}, 1)::Float64
SSAValue(20) = (((Base.arrayref)(D::Array{Float64,1}, 1)::Float64 / (Main.getindex)(Main.dx_aux, 1)::ANY)::ANY + (Base.mul_float)((Base.sub_float)((Base.sitofp)(Float64, 1)::Float64, (Base.arrayref)(AFDW::Array{Float64,1}, 1)::Float64)::Float64, (Base.arrayref)(v::Array{Float64,1}, 1)::Float64)::Float64)::ANY
SSAValue(19) = (Base.arrayref)(C::Array{Float64,1}, 1)::Float64
$(Expr(:inbounds, false))
# meta: location operators.jl * 424
SSAValue(22) = ((SSAValue(21) * SSAValue(20))::ANY * SSAValue(19))::ANY
# meta: pop location
$(Expr(:inbounds, :pop))
C_up::ANY = ((flux_up::Float64 + SSAValue(22))::ANY / ((Base.arrayref)(VF::Array{Float64,1}, 1)::Float64 * (((Base.arrayref)(D::Array{Float64,1}, 1)::Float64 / (Main.getindex)(Main.dx_aux, 1)::ANY)::ANY + (Base.mul_float)((Base.arrayref)(AFDW::Array{Float64,1}, 1)::Float64, (Base.arrayref)(v::Array{Float64,1}, 1)::Float64)::Float64)::ANY)::ANY)::ANY # line 11:
#200::##200#203 = $(Expr(:new, :(Main.##200#203)))
SSAValue(1) = $(Expr(:invoke, MethodInstance for -(::Array{Float64,1}), :(Main.-), :(VF)))
SSAValue(3) = (Main.vcat)(C_up::ANY, C::Array{Float64,1}, (Main.getindex)(C::Array{Float64,1}, Main.N)::ANY)::ANY
SSAValue(4) = (Main.getindex)(SSAValue(3), (Main.colon)(2, (Main.N + 2)::ANY)::ANY)::ANY
SSAValue(5) = (Main.vcat)(C_up::ANY, C::Array{Float64,1}, (Main.getindex)(C::Array{Float64,1}, Main.N)::ANY)::ANY
SSAValue(6) = (Main.getindex)(SSAValue(5), (Main.colon)(1, (Main.N + 1)::ANY)::ANY)::ANY
SSAValue(7) = (SSAValue(4) - SSAValue(6))::ANY
SSAValue(33) = D::Array{Float64,1}
SSAValue(34) = Main.dx_aux
$(Expr(:inbounds, false))
# meta: location broadcast.jl broadcast 434
SSAValue(26) = SSAValue(7)
SSAValue(27) = SSAValue(34)
# meta: location broadcast.jl containertype 34
SSAValue(25) = (Base.Broadcast.promote_containertype)(Array, (Base.Broadcast.promote_containertype)((Base.Broadcast._containertype)((Base.Broadcast.typeof)(SSAValue(26))::DataType)::ANY, (Base.Broadcast._containertype)((Base.Broadcast.typeof)(SSAValue(27))::DataType)::ANY)::ANY)::UNION{TYPE{ARRAY}, TYPE{BASE.SPARSEARRAYS.HIGHERORDERFNS.PROMOTETOSPARSE}}
unless (SSAValue(25) isa Type{Array})::Bool goto 37
#temp#@_16::Core.MethodInstance = MethodInstance for promote_containertype(::Type{Array}, ::Type{Array})
goto 46
37:
unless (SSAValue(25) isa Type{Base.SparseArrays.HigherOrderFns.PromoteToSparse})::Bool goto 41
#temp#@_16::Core.MethodInstance = MethodInstance for promote_containertype(::Type{Array}, ::Type{Base.SparseArrays.HigherOrderFns.PromoteToSparse})
goto 46
41:
goto 43
43:
#temp#@_17::ANY = (Base.Broadcast.promote_containertype)(Array, SSAValue(25))::UNION{TYPE{ARRAY}, TYPE{BASE.SPARSEARRAYS.HIGHERORDERFNS.PROMOTETOSPARSE}}
goto 48
46:
#temp#@_17::ANY = $(Expr(:invoke, :(#temp#@_16), :(Base.Broadcast.promote_containertype), Array, SSAValue(25)))
48:
# meta: pop location
# meta: pop location
$(Expr(:inbounds, :pop))
SSAValue(8) = (Base.Broadcast.broadcast_c)(#200::##200#203, #temp#@_17::ANY, SSAValue(1), SSAValue(33), SSAValue(7), SSAValue(34))::ANY
#201::##201#204 = $(Expr(:new, :(Main.##201#204)))
SSAValue(12) = ((Base.broadcast)(Main.*, AFDW::Array{Float64,1}, (Main.vcat)(C_up::ANY, C::Array{Float64,1})::ANY)::ANY + (Base.broadcast)(Main.*, $(Expr(:invoke, MethodInstance for -(::Int64, ::Array{Float64,1}), :(Main.-), 1, :(AFDW))), (Main.vcat)(C::Array{Float64,1}, (Main.getindex)(C::Array{Float64,1}, Main.N)::ANY)::ANY)::ANY)::ANY
$(Expr(:inbounds, false))
# meta: location broadcast.jl broadcast 434
# meta: location broadcast.jl containertype 34
SSAValue(28) = (Base.Broadcast.promote_containertype)(Array, (Base.Broadcast._containertype)((Base.Broadcast.typeof)(SSAValue(12))::DataType)::ANY)::UNION{TYPE{ARRAY}, TYPE{BASE.SPARSEARRAYS.HIGHERORDERFNS.PROMOTETOSPARSE}}
unless (SSAValue(28) isa Type{Array})::Bool goto 62
#temp#@_18::Core.MethodInstance = MethodInstance for promote_containertype(::Type{Array}, ::Type{Array})
goto 71
62:
unless (SSAValue(28) isa Type{Base.SparseArrays.HigherOrderFns.PromoteToSparse})::Bool goto 66
#temp#@_18::Core.MethodInstance = MethodInstance for promote_containertype(::Type{Array}, ::Type{Base.SparseArrays.HigherOrderFns.PromoteToSparse})
goto 71
66:
goto 68
68:
#temp#@_19::ANY = (Base.Broadcast.promote_containertype)(Array, SSAValue(28))::UNION{TYPE{ARRAY}, TYPE{BASE.SPARSEARRAYS.HIGHERORDERFNS.PROMOTETOSPARSE}}
goto 73
71:
#temp#@_19::ANY = $(Expr(:invoke, :(#temp#@_18), :(Base.Broadcast.promote_containertype), Array, SSAValue(28)))
73:
# meta: pop location
# meta: pop location
$(Expr(:inbounds, :pop))
SSAValue(13) = (Base.Broadcast.broadcast_c)(#201::##201#204, #temp#@_19::ANY, VF::Array{Float64,1}, v::Array{Float64,1}, SSAValue(12))::ANY
flux::ANY = (SSAValue(8) + SSAValue(13))::ANY # line 14:
(Main.setindex!)(flux::ANY, flux_up::Float64, 1)::ANY # line 15:
#202::##202#205 = $(Expr(:new, :(Main.##202#205)))
SSAValue(15) = -(((Main.getindex)(flux::ANY, (Main.colon)(2, (Main.N + 1)::ANY)::ANY)::ANY - (Main.getindex)(flux::ANY, (Main.colon)(1, Main.N)::ANY)::ANY)::ANY)::ANY
SSAValue(35) = VF_mid::Array{Float64,1}
SSAValue(36) = Main.dx
$(Expr(:inbounds, false))
# meta: location broadcast.jl broadcast 434
SSAValue(32) = (Base.Broadcast.promote_containertype)((Base.Broadcast._containertype)((Base.Broadcast.typeof)(SSAValue(15))::DataType)::ANY, (Base.Broadcast.promote_containertype)(Array, (Base.Broadcast._containertype)((Base.Broadcast.typeof)(SSAValue(36))::DataType)::ANY)::UNION{TYPE{ARRAY}, TYPE{BASE.SPARSEARRAYS.HIGHERORDERFNS.PROMOTETOSPARSE}})::ANY
# meta: pop location
$(Expr(:inbounds, :pop))
dC::ANY = (Base.Broadcast.broadcast_c)(#202::##202#205, SSAValue(32), SSAValue(15), SSAValue(35), SSAValue(36))::ANY # line 16:
return dC::ANY
end::ANY
我有几个问题。 (1)为什么预先分配的变量(dC
,C_up
,flux
)仍然具有类型any
? (2)如果我在函数外部定义了一个参数(常量),例如dx_aux
,那么将它包含在输入中是否有优势? (3)处理复杂的中间计算结果的最佳方法是什么?
答案 0 :(得分:3)
C_up
,flux
和dC
未在函数头中定义,因此我假设它们是全局变量。 Globals总是可以更改类型,因为
x = 3
x = 2.0
在REPL中工作,因此函数不会因为担心类型错误而专注于全局变量的类型。但是,如果它是常数,
const x = 3
然后编译器可以做出不会改变的假设,从而专注于类型并解决这个问题。请注意,数组的值是它们的引用,所以
const x = [3,4,5]
x[2] = 6
很好,因为x
的值只是引用,所以即使数组的内部值发生变化,它也不会改变。
(3)处理复杂的中间计算结果的最佳方法是什么?
像你这里的缓存数组,或带缓存的可调用类型,或者......,这太宽泛了,不能很好地回答。
我将留下两个链接:
http://www.stochasticlifestyle.com/7-julia-gotchas-handle/
它描述了全局变量问题及其发生的原因。但是:
https://github.com/JuliaLang/julia/issues/8870
建议使用新语法:
x::Int = 3
这样非常量全局变量可以具有在其他函数中推断的声明类型。这似乎不会使1.0,但它将是1.x。