【问题标题】:Julia, speeding up eval朱莉娅,加速评估
【发布时间】:2013-11-24 12:18:41
【问题描述】:

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 代码相同的速度?

编辑: 我可以使用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)

EDIT2:

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

我写了一个函数derivative(ex::Expr,arg::Symbol),它接受一个表达式和一个参数,并返回一个新的表达式,它是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))

【问题讨论】:

  • 你明白这在大多数应用程序中不应该是重要的吗?宏扩展(您可以在其中操作 julia 的 ast)通常发生在编译时,而不是运行时。所以这会稍微减慢编译速度,但不会减慢正在运行的程序。
  • @andrewcooke 好吧,这就是我的问题的重点。我可以执行myExpression() = compile(:(tan(pi/2*rand())))myExpression(x) = compile(:(tan(x))) 之类的操作来在运行时创建编译对象吗?

标签: julia


【解决方案1】:

如果你需要速度,你不应该使用 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() 进行性能测试

【讨论】:

  • 你说得对,我编辑了我的问题来描述我想用 Expr 做些什么。
  • 谢谢!我所做的只是将eval 替换为@eval,它为生成的代码提供了“本机速度”。
  • 请注意@eval 的参数必须在“编译”时可用,因此如果在函数中使用它,则只能访问全局变量。函数编译后,函数参数将被绑定。
猜你喜欢
  • 2021-05-04
  • 1970-01-01
  • 2018-11-27
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 2014-12-31
相关资源
最近更新 更多