我正在将我的代码从Julia 0.4更新为0.5,我遇到了一些减速。我遇到的一个简单例子是
x = rand(1:100, (50, 7, 3))
function f(a::Int, e::Int, r::Int)
x[a-16+1, e-10+1, r]
end
y = sum(f(a, e, r) for a in 16:65, e in 10:16, r in 1:3) # in 0.5 and 0.6
y = sum([f(a, e, r) for a in 16:65, e in 10:16, r in 1:3]) # in 0.4
在0.4中,最后一行(列表推导)需要0.0004秒,而在0.5和0.6中它需要大约0.1376。版本0.5和0.6中发生了什么?
答案 0 :(得分:10)
您在全局范围内使用非常量全局变量和时序代码。使x
保持不变(或将其作为函数参数传递)并将sum
计算放入函数中:
const x = rand(1:100, (50, 7, 3))
function f(a::Int, e::Int, r::Int)
x[a-16+1, e-10+1, r]
end
g() = sum(f(a, e, r) for a in 16:65, e in 10:16, r in 1:3) # in 0.5 and 0.6
h() = sum([f(a, e, r) for a in 16:65, e in 10:16, r in 1:3]) # in 0.4
我看到与运行原始代码时报告的时间几乎完全相同。使用我编写的代码:
0.6.0-pre.alpha.117:
julia> g(); @time g() # Call g() before timing it to compile it
0.000020 seconds (9 allocations: 416 bytes)
53033
julia> h(); @time h()
0.000026 seconds (6 allocations: 8.547 KiB)
53033
0.4.7:
julia> h(); @time h()
0.000020 seconds (6 allocations: 8.453 KB)
50658
它现在如此之快,你再也无法用一次运行来精确地对它进行基准测试。
是的,0.5和0.6确实在原始情况下变慢了。这是因为它现在为理解/生成器构造一个特殊的函数对象并编译它。因此,当您在顶层运行这些语句时,您每次都要支付(并测量)编译成本。当你把它放在一个函数中时,Julia能够编译一次,然后每个后续调用都非常快。如果您对优化效果感兴趣,我强烈建议您阅读所有performance tips。避免全局变量是第一部分。