2016-10-11 15 views
3

최근에 내 코드에서 유형 안정성 검사를 실행했습니다. 에 인수를 읽을 #temp#을 사용Julia @code_warntype 숨겨진 임시 변수 # temp #

Pkg.clone("https://github.com/klkeys/IHT.jl") 
n = 100; p = 250; k = 2; 
x = randn(n,p) 
b = zeros(p); b[1:k] = randn(k); shuffle!(b) 
y = x*b + randn(n) 
@code_warntype L0_reg(x, y, k, quiet=true) 

그것은 컴파일러처럼 보일 것입니다 : 내 IHT.jl 패키지를 사용하여,

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}} 

최소 동작하는 예제 : 나는 그것에 @code_warntype를 호출 할 때, 나는 다음과 같은 출력을 얻을 함수 L0_reg. 함수 인수는 완전히 지정됩니다. 어디에서이 작은 악의가 #temp#@_2 변수 발생합니까? 컴파일러에게 그 타입이 무엇인지 말할 수 있습니까?

답변

6

당신은 #temp# 변수가 어디에서 오는지 볼 수 @code_lowered을 사용할 수 있습니다 (희망하지 Array{Any,1} ...) :이 경우

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) 

, (특히 #temp#@_2 단위) 임시 직원 키워드 인수에서 오는 . 이것은 키워드 인수에 대해 아주 일반적입니다.

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 

키워드 인수는 callsite overhead that can be somewhat worked around by declaring types으로 알려져 있습니다. 함수가 거의 작동하지 않는 한, 키워드 인수를 정렬하는 것은 사실 괴로운 @code_warntype 출력에도 불구하고 큰 병목 현상이 아닐 수 있습니다.

키워드 인수 호출에서 @code_warntype을 수행하면 실제로 실제 함수 주위에 자동 생성 된 래퍼 인 키워드 인수 분류기의 유형이 불안정합니다. 보시다시피, 코드는 (IHT.#L0_reg#75)(temp,tol,max_iter,max_step,quiet,,x,y,k)을 호출하며, 이는 위치 인수를 취하는 일반 함수입니다. 따라서 @code_warntype의 출력은이 경우 거의 쓸모가 없습니다.

+0

그래서 "kw"와 "kwargs"변수가 의미하는 바는 ... 2 년 전이 사실을 알고 싶었습니다. X- ( –

+0

매우 철저한 답변에 감사드립니다! –