Julia 从@code\u warntype解释主体表达式

Julia 从@code\u warntype解释主体表达式,julia,Julia,如果我们运行: @code_warntype deepcopy(rand(2)) 在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},$(E

如果我们运行:

@code_warntype deepcopy(rand(2))
在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
我从中了解到,如果我们主要关心的是类型不稳定性,通常不需要担心Body表达式中的标记值。因此,我的问题是:


为什么来自
Base
的一个相当简单的函数会在
@code\u warntype
中生成任何标记值?我确信有很好的理由,但我对解释
@code\u warntype
的输出不太熟悉,在理解官方文档中对Body表达式的讨论时遇到了一些困难。

这是一个类型推断无法确定函数返回类型的情况示例。(注意返回值上的
::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)
请注意,第二个操作需要分配,并且需要时间,因为其中涉及拆箱和动态分派

在当前的夜间版本中,它将成为0.5(可能在几个月内发布),这一版本已经发布。因此

没有类型不稳定性,以及

julia> f()
  0.000000 seconds
  0.000000 seconds

它没有动态调度和分配。

感谢您的响应。你的答案很有趣!所以我碰巧从
Base
中选择了一个类型不稳定的函数。。。一个快速的澄清:我的问题中
返回
行末尾的
Any
结束
之后的下一行中的
Any
(即
end::Any
)之间有什么区别?在REPL处(在v0.4中)都有标记(红色字体)-都是指返回类型吗?@ColinTBowers在本例中,都是指返回类型,因为函数只在一个位置返回。有些函数可以从多个位置返回,对于这些函数,结束后的
Any
警告返回类型不稳定,即使每个返回语句都很好。明白。我经常编写具有多个返回位置的函数。再次感谢。我对答案进行了编辑,以澄清返回类型也是一个需要担心的问题。@Thoy理解。非常感谢。我还可以看出,修复是由您负责的,因此也非常感谢(我经常使用
deepcopy
):-)
julia> f()
  0.000000 seconds
  0.000000 seconds