2012-05-22 50 views
32

當使用範圍表達式對一個大型數組進行迭代時,是否應該使用Python的內置範圍函數或numpy的arange以獲得最佳性能?內置範圍或numpy.arange:哪個效率更高?

我到目前爲止的推理:

arange可能訴諸於本地實現,並且可能會更快,因此,另一方面,arange返回一個完整的數組,佔用內存,所以可能會有開銷。 Python 3的範圍表達式是一個生成器,它並不包含內存中的所有值。

回答

39

對於大型數組,numpy應該是更快的解決方案。

在numpy中,您應該使用矢量化計算組合ufuncsindexing解決您的問題,因爲它運行在C速度。 與此相比,循環播放numpy數組效率低下。你可以做的最糟糕的事情就是遍歷整個數組,其索引創建時使用rangenp.arange作爲你問題的第一句話,但我不確定你是否真的這麼認爲。)

import numpy as np 
import sys 

sys.version 
# out: '2.7.3rc2 (default, Mar 22 2012, 04:35:15) \n[GCC 4.6.3]' 
np.version.version 
# out: '1.6.2' 

size = int(1E6) 

%timeit for x in range(size): x ** 2 
# out: 10 loops, best of 3: 136 ms per loop 

%timeit for x in xrange(size): x ** 2 
# out: 10 loops, best of 3: 88.9 ms per loop 

# avoid this 
%timeit for x in np.arange(size): x ** 2 
#out: 1 loops, best of 3: 1.16 s per loop 

# use this 
%timeit np.arange(size) ** 2 
#out: 100 loops, best of 3: 19.5 ms per loop 

因此,對於這種情況下numpy的比使用xrange如果你這樣做是正確的快4倍。取決於你的問題,numpy比4倍或5倍加速要快得多。

this question的答案解釋了使用numpy數組代替python列表的大數據集的更多優點。

6

首先,如@bmu,所寫,您應該使用向量化計算的組合,ufuncs和索引。確實存在一些需要顯式循環的情況,但這些情況非常罕見。

如果需要顯式循環,使用python 2.6和2.7,你應該使用xrange(見下文)。從你說的,在Python 3中,範圍xrange(返回一個發生器)相同。所以也許範圍對你很好。

現在,你應該嘗試一下自己 (使用timeit: - 這裏的IPython的「神奇功能」):

%timeit for i in range(1000000): pass 
[out] 10 loops, best of 3: 63.6 ms per loop 

%timeit for i in np.arange(1000000): pass 
[out] 10 loops, best of 3: 158 ms per loop 

%timeit for i in xrange(1000000): pass 
[out] 10 loops, best of 3: 23.4 ms per loop 

此外,如上文提到的,大多數的時候,可以使用numpy的矢量/數組公式(或ufunc等)運行交流速度:快得多。這就是我們所說的「矢量編程」。它使程序比C更容易實現(並且更易讀),但最終速度幾乎一樣快。

+0

謝謝,我不知道魔術功能。 – clstaudt

+3

有一個標準的python'timeit'模塊,它允許在沒有IPython的情況下執行相同的操作。但是使用這個神奇功能要容易得多。 –

+0

-1因爲我認爲這不是一個好的基準。循環遍歷一個numpy數組效率不高。 – bmu

相關問題