Julia 學習筆記 - 計時
這裡我們要介紹 julia 計算程式執行時間的指令.
簡單來說,julia 計算程式運行效能有幾個指令:
@time
顯示出程式運行的秒數以及記憶體的使用狀況@timed
顯示程式執行回傳值,秒數以及記憶體的使用狀況@timev
顯示@time
一樣的資訊,最後顯示程式執行回傳值@elapsed
顯示出某程式運行的秒數
BUT, 真正要計算程式效能, 還是推薦用 BenchmarkTools.jl
這個 package.
以下範例中我們需要使用兩個 package: LinearAlgebra
以及 BenchmarkTools
using LinearAlgebra
using BenchmarkTools
Example 1: Matrix-matrix multiplication
我們以矩陣乘法 $C=A\times B$ 為例:$A:n\times p$, $B:p\times m$, $C:n\times m$
f1 這個函數會產生兩個隨機矩陣 $A$, $B$ 並且將他們相乘:
function f1(n, p, m)
A=rand(n,p)
B=rand(p,m)
C=zeros(Float64,n,m)
for i in 1:n
for j in 1:m
for k in 1:p
C[i,j] = C[i,j]+A[i,k]*B[k,j]
end
end
end
end
f1 (generic function with 1 method)
我們先試試看以 julia 既有的計算時間指令來看結果如何
@time f1(100,10,200)
0.076423 seconds (161.79 k allocations: 8.380 MiB)
@timed f1(100,10,200)
(nothing, 0.000448109, 184496, 0.0, Base.GC_Diff(184496, 1, 0, 5, 2, 0, 0, 0, 0))
@timev f1(100,10,200)
0.005932 seconds (8 allocations: 180.172 KiB, 92.28% gc time)
elapsed time (ns): 5931535
gc time (ns): 5473727
bytes allocated: 184496
pool allocs: 5
non-pool GC allocs:2
malloc() calls: 1
GC pauses: 1
@elapsed f1(100,10,200)
0.000561533
這些指令的表現如同一開始我們所介紹的, 顯示出程式執行時間以及其他資訊.
不過一般而言一個程式在第一次跑及之後幾次跑的運行效能會不同, 這是由於初始化的關係. 所以我們通常要跑好幾次來算平均, 已得知一個程式的真正效能.
benchmark
就提供了這樣的功用, 他會跑好幾次程式, 並且計算最大最小時間.
@benchmark f1(100,10,200)
BenchmarkTools.Trial:
memory estimate: 180.02 KiB
allocs estimate: 4
--------------
minimum time: 437.243 μs (0.00% GC)
median time: 485.922 μs (0.00% GC)
mean time: 513.114 μs (3.90% GC)
maximum time: 44.383 ms (98.89% GC)
--------------
samples: 9711
evals/sample: 1
接著我們看一下如果用 LinearAlgebra
裡的矩陣乘法指令效能如何.
function f2(n, p, m)
A=rand(n,p)
B=rand(p,m)
C=zeros(Float64,n,m)
mul!(C,A,B);
end
f2 (generic function with 1 method)
@benchmark f2(100,10,200)
BenchmarkTools.Trial:
memory estimate: 180.02 KiB
allocs estimate: 4
--------------
minimum time: 41.088 μs (0.00% GC)
median time: 91.270 μs (0.00% GC)
mean time: 106.954 μs (19.04% GC)
maximum time: 45.286 ms (99.75% GC)
--------------
samples: 10000
evals/sample: 1
看起來似乎比我們自己寫的 for-loop 效能好一些.
type-stability
julia 語言號稱效能非常好, 不過常常我們自己寫一個 julia 程式發現跑得沒有很快, 這通常是由於所謂的 “型別穩定性 type-stability”. 這樣的問題可以藉由以下幾個 julia 內建的巨集程式來診斷.
@code_warntype f1(10,10,10)
@code_typed f1(10,10,10)
@code_native f1(10,10,10)
這方面更深入的說明可見 julia: performance tips
Example 2: Vector 2-norm
接著我們看一下算向量 2-norm 的效能, 一樣我們比較一下自己寫的以及 call 函數的方式.
function t1(n)
vec = rand(1,n);
vec*vec';
end
t1 (generic function with 1 method)
@benchmark t1(10^5)
BenchmarkTools.Trial:
memory estimate: 781.42 KiB
allocs estimate: 3
--------------
minimum time: 423.973 μs (0.00% GC)
median time: 504.538 μs (0.00% GC)
mean time: 606.699 μs (9.87% GC)
maximum time: 47.376 ms (98.43% GC)
--------------
samples: 8213
evals/sample: 1
function t2(n)
vec = rand(1,n);
sum(abs2, vec);
end
t2 (generic function with 1 method)
@benchmark t2(10^5)
BenchmarkTools.Trial:
memory estimate: 781.33 KiB
allocs estimate: 2
--------------
minimum time: 141.160 μs (0.00% GC)
median time: 195.940 μs (0.00% GC)
mean time: 335.496 μs (19.51% GC)
maximum time: 64.500 ms (99.17% GC)
--------------
samples: 10000
evals/sample: 1
Example 3: Solving linear system
這裡我們看一下解線性系統, 也就是 matlab 常見的"左除", 的效率如何.
function s1(n)
A=rand(n,n);
b=rand(n);
A\b;
end
s1 (generic function with 1 method)
@benchmark s1(1000)
BenchmarkTools.Trial:
memory estimate: 15.28 MiB
allocs estimate: 8
--------------
minimum time: 13.463 ms (0.00% GC)
median time: 16.817 ms (10.20% GC)
mean time: 18.148 ms (9.36% GC)
maximum time: 64.226 ms (77.63% GC)
--------------
samples: 276
evals/sample: 1