【发布时间】: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