2017-03-16 18 views
2

我正在更新我的代碼從Julia 0.4到0.5,我遇到了一些放緩。我所遇到的一個簡單的例子是在0.5和0.6?

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

你怎麼知道它是一個0.5/0.6的放緩,而不是列表理解vs發生器表達式放慢? –

回答

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。避免全局是第一部分。

+0

假設我用'const x = rand(1:100,(50,7,3,50,7,3))'放大並且像你這樣將函數的和放入函數中。 0.5和0.6的表現顯着落後於0.4。然而,我注意到與顯式循環相加可以提高性能......將我的項目更改爲循環將是單調乏味的。 – amrods

+0

你使用的是什麼版本?在0.5.0上有6+維數組迴歸,已經固定在0.6-alpha上,並且大部分固定在0.5.1上。 –

+0

正是那些,0.5.1和0.6-pre-alpha(昨晚的版本)。我應該等待0.6的發佈嗎? – amrods