我正在用 julia 做一些實驗,因為我聽說它適用于科學微積分,而且它的語法讓人聯想到 python。我試圖撰寫并執行一個程式來計算某個 n 以下的素數,但表現并不是所希望的。在這里,我發布了我的代碼,并宣告我昨天已經開始使用 julia 編程,而且我幾乎可以肯定出現了問題:
n = 250000
counter = 0
function countPrime(counter)
for i = 1:n
# print("begin counter= ", counter, "\n")
isPrime = true
# print("i= ", i, "\n")
for j = 2:(i-1)
if (i%j) == 0
isPrime = false
# print("j= ", j, "\n")
break
end
end
(isPrime==true) ? counter = 1 : counter
# print("Counter= ", counter, "\n")
end
return counter
end
println(countPrime(counter))
事實上,用 C 移植的同一個程式有大約 5 秒的執行時間,而在 julia 中的這個程式有大約 3 分 50 秒,這對我來說聽起來很奇怪,因為我認為 julia 是一種編譯語言。發生了什么?
uj5u.com熱心網友回復:
這是我將如何更改它:
function countPrime(n)
counter = 0
for i in 1:n
isPrime = true
for j in 2:i-1
if i % j == 0
isPrime = false
break
end
end
isPrime && (counter = 1)
end
return counter
end
這段代碼在我的筆記本電腦上運行大約 5 秒。除了風格上的變化之外,主要的變化是你應該n作為引數傳遞給你的函式并counter在你的函式中定義變數。
這些更改遵循Julia Manual的Performance Tips部分中的第一個建議。
關鍵是當您使用全域變數時,Julia 編譯器無法對該變數的型別做出假設(因為它可能在函式編譯后發生變化),因此它防御性地假設它可能是任何東西,這會減慢速度向下。
至于風格變化請注意,(isPrime==true) ? counter = 1 : counter可以isPrime && (counter = 1)像您想要增加計數器一樣撰寫if isPrimeis true。? :這里不需要使用三元運算子。
要給出在函式中使用全域變數的問題的 MWE:
julia> x = 10
10
julia> f() = x
f (generic function with 1 method)
julia> @code_warntype f()
MethodInstance for f()
from f() in Main at REPL[2]:1
Arguments
#self#::Core.Const(f)
Body::Any
1 ─ return Main.x
你可以看到在f函式內部你參考了全域變數x。因此,當 Julia 編譯時,f它必須假設 的值x可以具有任何型別(在 Julia 中呼叫Any)。使用此類值很慢,因為編譯器無法使用任何優化來利用處理的更特定型別的值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/389798.html
上一篇:Numba中的型別串列與ND陣列
