以下几节将描述一些提高 Julia 代码运行速度的技巧。
全局变量的值、类型,都可能变化。这使得编译器很难优化使用全局变量的代码。应尽量使用局部变量,或者把变量当做参数传递给函数。
对性能至关重要的代码,应放入函数中。
声明全局变量为常量可以显著提高性能:
const DEFAULT_VAL = 0使用非常量的全局变量时,最好在使用时指明其类型,这样也能帮助编译器优化:
global x y = f(x::Int + 1)写函数是一种更好的风格,这会产生更多可重复和清晰的代码,也包括清晰的输入和输出。
@time
来衡量性能并且留心内存分配
衡量计算性能最有用的工具是 @time
宏。下面的例子展示了良好的使用方式 :
julia> function f(n) s = 0 for i = 1:n s += i/2 end s end f (generic function with 1 method) julia> @time f(1) elapsed time: 0.008217942 seconds (93784 bytes allocated) 0.5 julia> @time f(10^6) elapsed time: 0.063418472 seconds (32002136 bytes allocated) 2.5000025e11
在第一次调用时 (@time f(1)
), f
会被编译. (如果你在这次会话中还 没有使用过 @time
, 计时函数也会被编译.) 这时的结果没有那么重要. 在 第二次调用时, 函数打印了执行所耗费的时间, 同时请注意, 在这次执行过程中 分配了一大块的内存. 相对于函数形式的 tic
和 toc
, 这是 @time
宏的一大优势.
出乎意料的大块内存分配往往意味着程序的某个部分存在问题, 通常是关于类型 稳定性. 因此, 除了关注内存分配本身的问题, 很可能 Julia 为你的函数生成 的代码存在很大的性能问题. 这时候要认真对待这些问题并遵循下面的一些个建 议.
另外, 作为一个引子, 上面的问题可以优化为无内存分配 (除了向 REPL 返回结 果), 计算速度提升 30 倍
julia> @time f_improved(10^6) elapsed time: 0.00253829 seconds (112 bytes allocated) 2.5000025e11