Julia@code_warntype显示隐藏的临时变量#temp#

Julia@code_warntype显示隐藏的临时变量#temp#,julia,temporary,type-stability,Julia,Temporary,Type Stability,我最近对我的代码进行了类型稳定性检查。当我在上面调用@code\u warntype时,我得到以下输出: Variables: #unused#::IHT.#kw##L0_reg #temp#@_2::Array{Any,1} ::IHT.#L0_reg x::Array{Float64,2} y::Array{Float64,1} k::Int64 #temp#@_7::Bool #temp#@_8::Bool max_iter::Int64 max_s

我最近对我的代码进行了类型稳定性检查。当我在上面调用
@code\u warntype
时,我得到以下输出:

Variables:
  #unused#::IHT.#kw##L0_reg
  #temp#@_2::Array{Any,1}
  ::IHT.#L0_reg
  x::Array{Float64,2}
  y::Array{Float64,1}
  k::Int64
  #temp#@_7::Bool
  #temp#@_8::Bool
  max_iter::Int64
  max_step::Int64
  quiet::Bool
  v::IHT.IHTVariables{Float64,Array{Float64,1}}
  tol::Float64
  #temp#@_14::Int64
  #temp#@_15::Int64
  #temp#@_16::Int64
  #temp#@_17::Any
  ###...###
  #temp#@_17::Any = (Core.arrayref(#temp#@_2::Array{Any,1},#temp#@_16::Int64)::Any
  ###...###
  v::IHT.IHTVariables{Float64,Array{Float64,1}} = (Core.typeassert)((Core.arrayref)(#temp#@_2::Array{Any,1},(Base.box)(Int64,(Base.add_int)(#temp#@_16::Int64,1)))::Any,IHT.IHTVariables{Float64,Array{Float64,1}})::IHT.IHTVariables{Float64,Array{Float64,1}}
使用“我的软件包”的最小工作示例:


编译器似乎正在使用
#temp
读取函数
L0_reg
的参数。函数参数是完全指定的。这个邪恶的小
#temp@#u2
变量是从哪里产生的?我能告诉编译器它的类型是什么吗?(希望不是
Array{Any,1}
..)

您可以使用
@code\u
查看
#temp#
变量的来源:

julia> @code_lowered L0_reg(x, y, k, quiet=true)
LambdaInfo template for (::IHT.#kw##L0_reg){T<:Union{Float32,Float64}}(::Array{Any,1}, ::IHT.#L0_reg, x::DenseArray{T,2}, y::DenseArray{T,1}, k::Int64)
:(begin 
        NewvarNode(:(temp))
        NewvarNode(:(tol))
        #temp#@_7 = true
        #temp#@_8 = true
        max_iter = 100
        max_step = 50
        quiet = true
        SSAValue(0) = (IHT.colon)(1,(Base.length)(#temp#@_2) >> 1)
        #temp#@_14 = (Base.start)(SSAValue(0))
        10: 
        unless !((Base.done)(SSAValue(0),#temp#@_14)) goto 42
        SSAValue(1) = (Base.next)(SSAValue(0),#temp#@_14)
        #temp#@_15 = (Core.getfield)(SSAValue(1),1)
        #temp#@_14 = (Core.getfield)(SSAValue(1),2)
        #temp#@_16 = #temp#@_15 * 2 - 1
        #temp#@_17 = (Core.arrayref)(#temp#@_2,#temp#@_16)
        unless #temp#@_17 === :quiet goto 20
        quiet = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Bool)
        goto 40
        20: 
        unless #temp#@_17 === :max_step goto 24
        max_step = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Int)
        goto 40
        24: 
        unless #temp#@_17 === :max_iter goto 28
        max_iter = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Int)
        goto 40
        28: 
        unless #temp#@_17 === :tol goto 33
        tol = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Float)
        #temp#@_8 = false
        goto 40
        33: 
        unless #temp#@_17 === :temp goto 38
        temp = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),(Core.apply_type)(IHT.IHTVariables,$(Expr(:static_parameter, 1))))
        #temp#@_7 = false
        goto 40
        38: 
        (Base.kwerr)(#temp#@_2,,x,y,k)
        40: 
        goto 10
        42: 
        unless #temp#@_7 goto 45
        temp = (IHT.IHTVariables)(x,y,k)
        45: 
        unless #temp#@_8 goto 48
        tol = (IHT.convert)($(Expr(:static_parameter, 1)),0.0001)
        48: 
        return (IHT.#L0_reg#75)(temp,tol,max_iter,max_step,quiet,,x,y,k)
    end)
已知关键字参数具有。请注意,除非您的函数做得很少,否则关键字参数的排序实际上不太可能是一个巨大的瓶颈(尽管有讨厌的
@code\u warntype
输出)

当您对关键字参数调用执行
@code\u warntype
时,您实际上是在查看关键字参数排序器的类型不稳定性,它是围绕实际函数自动生成的包装器。如您所见,代码最终调用
(IHT.#L0_reg#75)(temp、tol、max#iter、max#u step、quiet、x、y、k)
,这是一个采用位置参数的普通函数。因此,在这种情况下,
@code\u warntype
的输出几乎是无用的。

这就是“kw”和“kwargs”变量的含义。。。我希望我两年前就知道这一点-(
julia> @code_lowered L0_reg(x, y, k, quiet=true)
LambdaInfo template for (::IHT.#kw##L0_reg){T<:Union{Float32,Float64}}(::Array{Any,1}, ::IHT.#L0_reg, x::DenseArray{T,2}, y::DenseArray{T,1}, k::Int64)
:(begin 
        NewvarNode(:(temp))
        NewvarNode(:(tol))
        #temp#@_7 = true
        #temp#@_8 = true
        max_iter = 100
        max_step = 50
        quiet = true
        SSAValue(0) = (IHT.colon)(1,(Base.length)(#temp#@_2) >> 1)
        #temp#@_14 = (Base.start)(SSAValue(0))
        10: 
        unless !((Base.done)(SSAValue(0),#temp#@_14)) goto 42
        SSAValue(1) = (Base.next)(SSAValue(0),#temp#@_14)
        #temp#@_15 = (Core.getfield)(SSAValue(1),1)
        #temp#@_14 = (Core.getfield)(SSAValue(1),2)
        #temp#@_16 = #temp#@_15 * 2 - 1
        #temp#@_17 = (Core.arrayref)(#temp#@_2,#temp#@_16)
        unless #temp#@_17 === :quiet goto 20
        quiet = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Bool)
        goto 40
        20: 
        unless #temp#@_17 === :max_step goto 24
        max_step = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Int)
        goto 40
        24: 
        unless #temp#@_17 === :max_iter goto 28
        max_iter = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Int)
        goto 40
        28: 
        unless #temp#@_17 === :tol goto 33
        tol = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),IHT.Float)
        #temp#@_8 = false
        goto 40
        33: 
        unless #temp#@_17 === :temp goto 38
        temp = (Core.typeassert)((Core.arrayref)(#temp#@_2,#temp#@_16 + 1),(Core.apply_type)(IHT.IHTVariables,$(Expr(:static_parameter, 1))))
        #temp#@_7 = false
        goto 40
        38: 
        (Base.kwerr)(#temp#@_2,,x,y,k)
        40: 
        goto 10
        42: 
        unless #temp#@_7 goto 45
        temp = (IHT.IHTVariables)(x,y,k)
        45: 
        unless #temp#@_8 goto 48
        tol = (IHT.convert)($(Expr(:static_parameter, 1)),0.0001)
        48: 
        return (IHT.#L0_reg#75)(temp,tol,max_iter,max_step,quiet,,x,y,k)
    end)
julia> f(; x=1) = x
f (generic function with 1 method)

julia> @code_warntype f(x=1)
Variables:
  #unused#::#kw##f
  #temp#@_2::Array{Any,1}
  ::#f
  x::Any
  #temp#@_5::Int64
  #temp#@_6::Int64
  #temp#@_7::Int64
  #temp#@_8::Any

Body:
  begin 
      x::Any = 1
      SSAValue(2) = (Base.arraylen)(#temp#@_2::Array{Any,1})::Int64
      SSAValue(3) = (Base.select_value)((Base.sle_int)(0,1)::Bool,(Base.box)(Int64,(Base.ashr_int)(SSAValue(2),(Base.box)(UInt64,1))),(Base.box)(Int64,(Base.shl_int)(SSAValue(2),(Base.box)(UInt64,(Base.box)(Int64,(Base.neg_int)(1))))))::Int64
      SSAValue(4) = (Base.select_value)((Base.sle_int)(1,SSAValue(3))::Bool,SSAValue(3),(Base.box)(Int64,(Base.sub_int)(1,1)))::Int64
      #temp#@_5::Int64 = 1
      6: 
      unless (Base.box)(Base.Bool,(Base.not_int)((#temp#@_5::Int64 === (Base.box)(Int64,(Base.add_int)(SSAValue(4),1)))::Bool)) goto 21
      SSAValue(5) = #temp#@_5::Int64
      SSAValue(6) = (Base.box)(Int64,(Base.add_int)(#temp#@_5::Int64,1))
      #temp#@_6::Int64 = SSAValue(5)
      #temp#@_5::Int64 = SSAValue(6)
      #temp#@_7::Int64 = (Base.box)(Int64,(Base.sub_int)((Base.box)(Int64,(Base.mul_int)(#temp#@_6::Int64,2)),1))
      #temp#@_8::Any = (Core.arrayref)(#temp#@_2::Array{Any,1},#temp#@_7::Int64)::Any
      unless (#temp#@_8::Any === :x)::Bool goto 17
      x::Any = (Core.arrayref)(#temp#@_2::Array{Any,1},(Base.box)(Int64,(Base.add_int)(#temp#@_7::Int64,1)))::Any
      goto 19
      17: 
      (Base.throw)($(Expr(:new, :(Base.MethodError), :((Core.getfield)((Core.getfield)((Core.getfield)(#f,:name)::TypeName,:mt),:kwsorter)), :((Core.tuple)(#temp#@_2,)::Tuple{Array{Any,1},#f}))))::Union{}
      19: 
      goto 6
      21: 
      return x::Any
  end::Any