Matlab, R, Python關於向量化計算和for循環的速度比較?
Matlab和R,有這樣一個特點:向量化運算速度快,但是用for循環速度很慢。
Python有沒有這樣的問題?
向量化運算的話,這些軟體都是通過C/C++,Fortran寫的庫實現的,所以速度差不多。
for循環的話,以我的經驗,安裝原裝語言,不考慮相關庫和編譯優化的情況下,速度從快到慢的排序是MATLAB,Python, R。MATLAB自R2015b後,循環速度又有大幅度提升。提速的話,考慮mex。mex的編寫與調試不方便(代碼如果有bug,經常MATLAB崩掉),不是萬不得已,我一般不用。Python主要優勢是它的易用性,需要性能時,可以考慮使用效率高的庫,也可以使用numba,cython,pypy來大幅度提高性能。
R的循環最慢,但是使用它的人,一般不自己寫演算法,一般都是直接調用相關的庫。以Falccm用的例子為例:MATLAB的R2016a:tic;
s = 0;
for k = 1:1e9
s = s + k;
end
toc;
s
結果:
時間已過 3.904714 秒。
s =
5.00000000067109e+17
計算結果有誤差,因為使用的是浮點型。
Python 2.7.11:import time
from numba import jit
@jit
def testSum():
s = 0
for k in range(1, 1000000001): # 1e9
s += k
return s
t = time.clock()
s = testSum()
print time.clock() - t
print s
結果:
0.023960742777
500000000500000000
計算結果沒有誤差,而且速度更快。
加入numba並不麻煩,僅僅增加了兩行:from numba import jit
@jit
通過添加變數類型,可以進一步提高性能:
1.3. Compiling Python code with @jitimport time
from numba import jit, int64
@jit(int64())
def testSum():
s = 0
for k in range(1, 1000000001): # 1e9
s += k
return s
t = time.clock()
s = testSum()
print time.clock() - t
print s
結果:
3.01848604067e-06
500000000500000000
tic;
s = 0;
for k = 1:1e9
s = s/3;
s = s + k;
end
toc;
s
結果:
時間已過 9.160245 秒。
s =
1499999999.25
Python 2.7.11:
import time
from numba import jit, float64
@jit(float64())
def testSum():
s = 0.0
for k in range(1, 1000000001): # 1e9
s /= 3.0
s += 1.0 * k
return s
t = time.clock()
s = testSum()
print time.clock() - t
print s
結果:
6.86019338233
1499999999.25
Python+Numba略快。
function res = fib(n)
if n &< 0
error("n must be non-negative");
end
if n &< 2
res = n;
return
end
res = fib(n-1) + fib(n-2);
end
tic;disp(fib(35));toc;
結果:
9227465
時間已過 1.597194 秒。
Python 2.7.11:
import time
#from numba import jit
#@jit
def fib(n):
if n &< 0:
print "n must be non-negative"
return
if n &< 2:
return n
return fib(n - 1) + fib(n - 2)
t = time.clock()
s = fib(35)
print time.clock() - t
print s
結果:
3.6433592249
9227465
R 不清楚,不過 MATLAB 目前循環速度已經比原來快很多了:
function testSum
s = 0;
for k = 1:1e9
s = s + k;
end
&>&> tic, testSum; toc
時間已過 4.364448 秒。
雖然很多情況下有比簡單循環更好的寫法,但是至少沒有必要像之前那樣懼怕循環了。可能很多比較經(guo)典(shi)的資料和 MATLAB 版本會讓你對循環性能存在一定誤解
python 的循環反正不快,經常用作 MATLAB 替代的 numpy 也確實有向量化比循環快的情況試了下 Python:
def testSum():
s = 0
for k in range(1, 100000001): # 1e8
s += k
t = time.clock()
testSum()
print("用時:", time.clock() - t, "秒")
用時: 5.859156802823201 秒
是慢了一點,上邊 python 測試用的是1e8的數據已經比 MATLAB 1e9的慢了
不過參見另一個答案,可以用 Numba 對 python 的循環進行加速,在一些情況下可以達到甚至超過 MATLAB 循環的效果。不過 Numba 適用範圍好像有一定限制,某些情況下可能不如 Python 本身的性能,總之只要使用得當應該是很有利的工具r是解釋型的,所以for的速度是有瓶頸。
最好的辦法是優化代碼,官網上的task view裡面有很多高效運算包d
matlab py沒學的那麼深入,就不評價了推薦閱讀:
※python中的漢諾塔遞歸演算法的具體運算過程是怎樣的?
※Python 里為什麼函數可以返回一個函數內部定義的函數?
※為何大量設計模式在動態語言中不適用?
※python如何繪製一個橫坐標為字元串,縱坐標為數字的折線圖?
※python 的 dict真的不會隨著key的增加而變慢嗎?