4

Julia 具有访问自己的语法树的非常好的特性,这使得以编程方式生成新函数变得容易,但它比普通的 Julia 代码慢得多。

例如:

julia> timing = @time for i in [1:100] tan(pi/2*rand()); end
elapsed time: 1.513e-5 seconds (896 bytes allocated)

julia> timing = @time for i in [1:100] x = pi/2*rand(); eval(:(tan(x))); end
elapsed time: 0.0080231 seconds (23296 bytes allocated)

julia> timing = @time for i in [1:100]  eval(:(tan(pi/2*rand()))); end
elapsed time: 0.017245327 seconds (90496 bytes allocated)

有没有办法提供eval与普通 Julia 代码相同的速度?

编辑:我能够使用该函数稍微加快 eval 的速度precompile,但这还不够:

julia> tmp3 = :(sin(x))
:(sin(x))

julia> timing = @time for i in [1:100000] x = pi/2*rand(); eval(tmp3); end
elapsed time: 8.651145772 seconds (13602336 bytes allocated)

julia> precompile(tmp3,(Float64,Float64))

julia> timing = @time for i in [1:100000] x = pi/2*rand(); eval(tmp3); end
elapsed time: 8.611654016 seconds (13600048 bytes allocated)

编辑2:

@Ivarne 建议我提供有关我的项目的详细信息。好吧,我想使用 Julia 的元编程功能来计算符号导数并运行它们。

我写了一个函数derivative(ex::Expr,arg::Symbol),它接受 and 表达式和一个参数,并返回一个新表达式,它是ex相对于的导数arg。不幸的是,Expr评估结果需要很长时间。

EDIT3:作为结论,使用@eval代替的表演eval

julia> timing = @time for i in [1:100000] x = pi/2*rand(); @eval(tmp3); end
elapsed time: 0.005821547 seconds (13600048 bytes allocated)

tmp3还是:(sin(x))

4

1 回答 1

7

如果你需要速度,你不应该使用 eval,因为每次都需要做很多工作来生成优化的快速代码。

如果要操作表达式,则应改为查看宏。它们对表达式进行操作并返回将编译一次的表达式。请参阅http://docs.julialang.org/en/latest/manual/metaprogramming/

如果您提供有关问题的一些详细信息,而不仅仅是对 eval 进行性能测试,那么将更容易为您指明正确的方向。让 julia 中的 eval 更快是一个项目,而不是 StackOverflow 的问题。

编辑: Calculus.jl中已经有一些功能,我认为最好执行以下操作:

myexpr = :(sin(x))
myexpr_dx = derivative(myxpr)
@eval myfun(x) = $myexpr
@eval myfun_dx(x) = $myexpr_dx 

这样您就可以得到一个可以评估的函数而不是表达式。然后您可以对 myfun(x) 和 myfun_dx() 进行性能测试

于 2013-11-24T20:12:13.980 回答