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