当函数被传递给函数时,Julia编译器似乎不会进行优化

当函数被传递给函数时,Julia编译器似乎不会进行优化,julia,Julia,第二次编辑:在github上将修复此问题。只要运行Julia v0.5+,匿名函数将与常规函数一样快。所以案子结束了 编辑:我已将问题和函数定义更新为更一般的情况 举个简单的例子,当一个函数被传递给一个函数或函数中定义了一个函数时,Julia编译器似乎不会进行优化。这让我感到惊讶,因为这在优化包中非常常见。我是对的还是做了傻事?下面是一个简单的例子: f(a::Int, b::Int) = a - b #A simple function function g1(N::Int, fIn:

第二次编辑:在github上将修复此问题。只要运行Julia v0.5+,匿名函数将与常规函数一样快。所以案子结束了

编辑:我已将问题和函数定义更新为更一般的情况

举个简单的例子,当一个函数被传递给一个函数或函数中定义了一个函数时,Julia编译器似乎不会进行优化。这让我感到惊讶,因为这在优化包中非常常见。我是对的还是做了傻事?下面是一个简单的例子:

f(a::Int, b::Int) = a - b    #A simple function

function g1(N::Int, fIn::Function)   #Case 1: Passing in a function
    z = 0
    for n = 1:N
        z += fIn(n, n)
    end
end

function g2(N::Int)   #Case 2: Function defined within a function
    fAnon = f
    z = 0
    for n = 1:N
        z += fAnon(n, n)
    end
    return(z)
end

function g3(N::Int)   #Case 3: Function not defined within function
    z = 0
    for n = 1:N
        z += f(n, n)
    end
    return(z)
end
然后,我运行以下代码来计时这三种情况:

#Run the functions once
g1(10, f)   
g2(10)
g3(10)

@time g1(100000000, f)
@time g2(100000000)
@time g3(100000000)
时间安排如下:

elapsed time: 5.285407555 seconds (3199984880 bytes allocated, 33.95% gc time)
elapsed time: 5.424531599 seconds (3199983728 bytes allocated, 32.59% gc time)
elapsed time: 2.473e-6 seconds (80 bytes allocated)

前两种情况下会有大量内存分配和垃圾回收。有人能解释一下原因吗?

所以一件有趣的事情是在Julia 0.4中使用
@code\u warntype
,它显示了以下内容:

julia> @code_warntype g1(10, f)
Variables:
  N::Int64
  fIn::F
  z::Any
  #s1::Int64
  n::Int64

Body:
  begin  # none, line 2:
      z = 0 # line 3:
... snip ....
      z = z + (fIn::F)(n::Int64,n::Int64)::Any::Any

所以问题在于推断
f
的返回类型,它实际上可能是任何东西。问题是(据我所知)Julia为每个类型组合编译了一个方法。我们已经为任何函数生成了代码,所以任何东西都可以返回。如果
函数
在返回类型上是参数化的,那就很好了,因为这样我们就可以做一些更聪明的事情,比如
函数{T这在Julia v0.5中得到了修复。现在所有三种情况都应该提供与
g3
相同的性能。

非常有用的答案,谢谢。您是否认为在开发周期的这一点上,如果性能至关重要,应该避免将函数作为参数传递给函数?再次感谢。我认为这更取决于mes函数将被调用。如果被调用的函数运行得很快,并且被调用了很多次,这将是相当糟糕的。如果函数被调用了几次,并且它只是整个程序的一小部分,或者函数需要更长的时间来执行,那么它就可以了。
(top(typeassert))((fIn::F)(n::Int64,n::Int64)::Any,Int)::Int64
julia> @time g1(1000000, f)
elapsed time: 0.124437357 seconds (30 MB allocated, 2.82% gc time in 1 pauses with 0 full sweep)
elapsed time: 0.121653131 seconds (30 MB allocated, 2.51% gc time in 2 pauses with 0 full sweep)
elapsed time: 0.120805345 seconds (30 MB allocated, 1.17% gc time in 1 pauses with 0 full sweep)

julia> @time g1A(1000000, f)
elapsed time: 0.085875439 seconds (30 MB allocated, 5.20% gc time in 1 pauses with 0 full sweep)
elapsed time: 0.074592531 seconds (30 MB allocated, 4.67% gc time in 2 pauses with 0 full sweep)
elapsed time: 0.078681071 seconds (30 MB allocated, 4.75% gc time in 1 pauses with 0 full sweep)