【问题标题】:Interpreting Body expression from @code_warntype从@code_warntype 解释正文表达式
【发布时间】:2016-06-17 03:24:47
【问题描述】:

如果我们运行:

@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

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

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

【问题讨论】:

  • 我编辑了这个答案,以便澄清返回类型也是需要担心的问题。
  • @tholy 明白了。非常感谢。我也可以看到你负责修复,所以也感谢(我经常使用deepcopy):-)

标签: julia


【解决方案1】:

这是类型推断无法确定函数的返回类型的示例。 (注意返回值上的::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(可能会在几个月内发布)的当前夜间版本中,这是 fixed。因此

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}

没有类型不稳定性,并且

julia> f()
  0.000000 seconds
  0.000000 seconds

没有动态调度和分配。

【讨论】:

  • 感谢您的回复。你的回答很有趣!所以我碰巧从Base 中选择了一个类型不稳定的函数......一个快速澄清:我的问题中return 行末尾的Any 和@987654329 有什么区别@ 在end 之后的下一行中(即end::Any)?两者都在 REPL(在 v0.4 中)标记(红色字体) - 两者都引用返回类型吗?
  • @ColinTBowers 在这个例子中,两者都指返回类型,因为函数只返回一个地方。一些函数有多个可以返回的位置,对于这些函数,即使每个单独的 return 语句都没有问题,结束后的 Any 也会警告返回类型不稳定。
  • 明白。我经常编写具有多个返回位置的函数。再次感谢。
猜你喜欢
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
相关资源
最近更新 更多