2016-05-01 94 views
4

我PI aproximation代碼非常相似,官方網頁上:朱莉婭PI aproximation慢

function piaprox() 
    sum = 1.0 
    for i = 2:m-1 
     sum = sum + (1.0/(i*i)) 
    end 
end 

m = parse(Int,ARGS[1]) 
opak = parse(Int,ARGS[2]) 

@time for i = 0:opak 
    piaprox() 
end 

當我嘗試比較C和朱莉婭的時間,然後Julia是顯著慢,對於m近38秒= 100000000(C的時間是0.1608328933秒)。爲什麼發生這種情況?

回答

14
julia> m=100000000 
julia> function piaprox() 
      sum = 1.0 
      for i = 2:m-1 
       sum = sum + (1.0/(i*i)) 
      end 
     end 
piaprox (generic function with 1 method) 

julia> @time piaprox() 
28.482094 seconds (600.00 M allocations: 10.431 GB, 3.28% gc time) 

我想從朱莉婭文檔Performance Tips節提兩個非常重要的段落:

Avoid global variables一個全局變量可能有它的價值,因此 它的類型,改變在任何點。這使編譯器難以使用全局變量優化代碼。變量應該 是本地的,還是作爲函數的參數,儘可能通過.....

@code_warntype(或它的功能變異code_warntype())可以 有時在診斷類型相關的問題有幫助。

julia> @code_warntype piaprox(); 
Variables: 
    sum::Any 
    #s1::Any 
    i::Any 

這是一個從@code_warntype輸出編譯器無法識別類型的局部變量的piaprox()清楚。因此,我們試圖聲明類型和刪除全局變量:

function piaprox(m::Int) 
    sum::Float64 = 1.0 
    i::Int = 0 
    for i = 2:m-1 
     sum = sum + (1.0/(i*i)) 
    end 
end 
julia> @time piaprox(100000000) 
    0.009023 seconds (11.10 k allocations: 399.769 KB) 
julia> @code_warntype piaprox(100000000); 
Variables: 
    m::Int64 
    sum::Float64 
    i::Int64 
    #s1::Int64 

編輯

爲@ user3662120評論,答案的超快行爲是一個錯誤的結果,沒有返回值LLVM可能會忽略for循環,通過添加一個返回線@time結果將是:

julia> @time piaprox(100000000) 
    0.746795 seconds (11.11 k allocations: 400.294 KB, 0.45% gc time) 
1.644934057834575 
+4

請注意,'m'和'sum'上的類型註釋對於速度不是必需的。 – StefanKarpinski

+2

類型註釋(:: Int,:: Float64)實際上並沒有對性能做任何貢獻。 (添加無用類型註釋是一個常見的Julia錯誤。)還要注意,您忘記返回總和。 (LLVM實際上可以優化整個循環!) – SGJ