朱莉娅,加速了eval

S4M*_*S4M 3 julia

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)
Run Code Online (Sandbox Code Playgroud)

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

编辑:我能够使用该precompile功能略微加速eval ,但仍然不够:

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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

tmp3 还是 :(sin(x))

iva*_*rne 6

如果你需要速度,你不应该使用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 
Run Code Online (Sandbox Code Playgroud)

因此,您可以获得一个函数,而不是表达式.然后,您可以对myfun(x)和myfun_dx()进行性能测试

  • 谢谢!我所做的只是用@eval替换了eval,它给了生成的代码“ native speed”。 (2认同)