从@code_warntype解释Body表达式

Col*_*ers 4 julia

如果我们运行:

@code_warntype deepcopy(rand(2))
Run Code Online (Sandbox Code Playgroud)

在Julia REPL中,输出包含Body表达式中的标记值.具体来说,两个Any在结尾:

Body:
  begin  # deepcopy.jl, line 8:
      GenSym(0) = (Base.Array)(Base.Any,32)::Array{Any,1}
      return (Base.deepcopy_internal)(x::Array{Float64,1},$(Expr(:new, :((top(getfield))(Base,:ObjectIdDict)::Type{ObjectIdDict}), GenSym(0))))::Any
  end::Any
Run Code Online (Sandbox Code Playgroud)

我从这个问题中了解到,如果主要关注的是类型不稳定,我们通常不需要担心Body表达式中的标记值.相反,我的问题是:

为什么Base生成任何标记值的相当简单的函数@code_warntype?我确信有充分的理由,但我是新解释的输出@code_warntype,并且在从官方文档中理解Body表达式的讨论时遇到了一些麻烦.

Fen*_*ang 5

这是类型推断无法确定函数的返回类型的情况的示例.(注意::Any返回值!)这一个问题,不是因为类型不稳定而计算本身会变慢,而是因为无法推断返回类型,因此使用返回类型的未来计算将受到类型不稳定的影响.

您可以通过查看以下分配来查看此效果:

julia> function f()
         y = rand(10)
         @time y[1] + y[10]
         z = deepcopy(y)
         @time z[1] + z[10]
       end
f (generic function with 1 method)

julia> f();  # ignore output here on first compile

julia> f();
  0.000000 seconds
  0.000002 seconds (3 allocations: 48 bytes)
Run Code Online (Sandbox Code Playgroud)

请注意,第二个操作需要分配并需要时间,因为涉及拆箱和动态分派.

在目前的每晚构建0.5(可能会在几个月内发布),这已得到修复.从而

julia> @code_warntype deepcopy(rand(2))
Variables:
  #self#::Base.#deepcopy
  x::Array{Float64,1}

Body:
  begin  # deepcopy.jl, line 8:
      # meta: location dict.jl Type # dict.jl, line 338:
      SSAValue(1) = (Core.ccall)(:jl_alloc_array_1d,(Core.apply_type)(Core.Array,Any,1)::Type{Array{Any,1}},(Core.svec)(Core.Any,Core.Int)::SimpleVector,Array{Any,1},0,32,0)::Array{Any,1}
      # meta: pop location
      return (Core.typeassert)((Base.deepcopy_internal)(x::Array{Float64,1},$(Expr(:new, :(Base.ObjectIdDict), SSAValue(1))))::Any,Array{Float64,1})::Array{Float64,1}
  end::Array{Float64,1}
Run Code Online (Sandbox Code Playgroud)

没有类型不稳定,和

julia> f()
  0.000000 seconds
  0.000000 seconds
Run Code Online (Sandbox Code Playgroud)

没有动态调度和没有分配.

  • 谢谢你的回复.你的答案非常有趣!所以我碰巧从"Base"中选择了一个类型不稳定的函数......一个简单的说明:在我的问题的`return`行末尾的`Any`和`Any之间有什么区别? `在`end`之后的下一行(即`end :: Any`)?两者都在REPL标记(红色字体)(在v0.4中) - 两者都引用返回类型? (2认同)
  • @ColinTBowers在这个例子中,两者都引用了返回类型,因为该函数只返回一个地方.有些函数有多个可以返回的位置,对于那些函数,结束后的"Any"警告返回类型不稳定,即使每个单独的return语句都没问题. (2认同)