在哪些方面,Numpy的速度反而比不上原始Python?
本來只是想測試下numpy處理數組索引時是不是從頭到尾順序查找的,就寫了這一段:
import numpy as np
a = np.random.rand(100)
b = a.tolist()
%timeit a[0]
%timeit a[50]
%timeit a[99]
%timeit b[0]
%timeit b[50]
%timeit b[99]
結果很有意思
10000000 loops, best of 3: 178 ns per loop
10000000 loops, best of 3: 187 ns per loop
10000000 loops, best of 3: 189 ns per loop
10000000 loops, best of 3: 82 ns per loop
10000000 loops, best of 3: 74 ns per loop
10000000 loops, best of 3: 74.2 ns per loop
也就是說numpy查找一個下標時應該是順序的(查找a[0]快於a[50]快於a[99])
標準的list反而不是順序的(查找a[50]快於a[99]快於a[0])
最關鍵的是!numpy array比list要慢一倍以上!不能忍啊!
不過想想也是,numpy array是一個複雜的結構體,list就只是個list···
這樣的話,要優化代碼,把原始碼盡量改成Numpy就沒有意義了···
我的問題就在這裡了,在處理什麼任務時,Numpy的數據結構和函數反而不如原始Python更快?
很有意思的結果。我不清楚numpy數組在哪些場合下慢過list,不過糾正一下題主的誤解。
python的list實現不是鏈表,而是動態數組。動態數組append/pop的均攤時間複雜度為O(1),而按下標隨機訪問跟一般數組無異,時間複雜度嚴格為O(1)。C++ STL中的vector也是動態數組。當然,從非尾部增刪元素也是支持的,雖然慢就是了,應避免。
關於python各種內建類型操作的時間複雜度,可參考TimeComplexity
關於動態數組,可參考Dynamic array
另外numpy數組單個元素隨機訪問比list慢沒啥大不了的,後者是python實現內建,前者還有ffi的開銷。numpy快的地方在於可以整向量/整矩陣地做算術運算,中間省了許多開銷。你寫個list comprehension來用list模擬向量算術,再來跟numpy比,會有質的不同。哪怕沒鏈MKL優化的numpy也能把list爆出翔。你這個問題其實不說明numpy比原始的Python慢,而是說明了數據轉換是有性能損耗的。
numpy內部存儲數據是和C語言一致的,比如一個這裡100個np.float64的元素就是內存中緊密排列的100個double數字。
而Python里的所有東西,包括簡單的數字,全都是PyObject的指針,每個PyObject都要在堆上分配,記錄引用計數,類型等許多bookkeeping的數據。你訪問a[0]時,這個數字本來只是一個簡單的double,但是返回到Python裡面就需要在堆上分配並加很多額外信息;而b[0]不同,Python里的list本來就是PyObject *的數組,這些額外的信息都創建好了,所以更快。
這唯一告訴我們的就是,不要把numpy的計算和Python內置的功能混在一起用,除了到了最後輸入輸出的時候。
很無聊的問題。同意bhuztez,Erlang無證腦殘粉 說的。兩者的速度差很小。如果你要平凡操作的話,那還不如直接用C寫個擴展。否則純屬自己創造問題,減低工作效率
你這個有點讓納什踢足球然後看他舔腳的感覺……python把事情給numpy的時候是要轉換數據的,反過來也是一樣如果對數據處理過程時間的節約不足抵消轉換這些時間,那還是python自己解決比較好嘛_(:з」∠)_話說題主你不妨試試numexpr→_→大數組跑起來飛快但是切片這種事一定不會比numpy快www話說切片這活難道不是額外的trick一樣的功能么_(:з」∠)_
除了單元素訪問,我又測試了下數組切片的性能Test1:
import numpy as np
mat = np.zeros(100).reshape(-1,5) #20*5的矩陣
a = mat
b = mat.reshape(-1,)
c = mat.tolist()
%timeit a[:,3]
%timeit b[3::5]
%timeit c[3::5]
我要獲取一個5*200矩陣中第4列的所有元素,這種操作挺常見的。三個操作效果是等價的,耗時分別是:(注意最後一個的單位)
100000 loops, best of 3: 2.18 μs per loop
1000000 loops, best of 3: 1.29 μs per loop
1000000 loops, best of 3: 332 ns per loop
還是list更快,比numpy同等操作快了三倍以上···另外numpy內部的切片性能差距也挺大
Test2:元素數目加到1000mat = np.zeros(1000).reshape(-1,5)
結果顯示速度差距變小了(list的操作耗時增加,numpy的兩種操作耗時甚至略有下降!)
100000 loops, best of 3: 2.16 μs per loop
1000000 loops, best of 3: 1.28 μs per loop
1000000 loops, best of 3: 442 ns per loop
mat = np.zeros(10000).reshape(-1,5)
結果顯示numpy穩如泰山,list耗時正式超過numpy···
100000 loops, best of 3: 2.16 μs per loop
1000000 loops, best of 3: 1.29 μs per loop
100000 loops, best of 3: 2.11 μs per loop
推薦閱讀:
※fMRI experiment Design:GLM引發的一些實驗設計要求
※Dynamic Causal Modeling:確定性因果模型(上)
※複雜數據處理(下):1816-2013年拉薩年平均氣溫變化分析