朱莉娅功能型不稳定

时间:2017-12-05 05:44:33

标签: julia

仍然有点困惑,要在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)为什么预先分配的变量(dCC_upflux)仍然具有类型any? (2)如果我在函数外部定义了一个参数(常量),例如dx_aux,那么将它包含在输入中是否有优势? (3)处理复杂的中间计算结果的最佳方法是什么?

1 个答案:

答案 0 :(得分:3)

C_upfluxdC未在函数头中定义,因此我假设它们是全局变量。 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。