2012-06-06 176 views
30

使用Python的原生sum函數和NumPy的numpy.sum之間的性能和行爲有什麼區別? sum適用於NumPy的數組,numpy.sum適用於Python列表,它們都返回相同的有效結果(未測試溢出等邊緣情況),但返回不同的類型。Python的總和與NumPy的numpy.sum

>>> import numpy as np 
>>> np_a = np.array(range(5)) 
>>> np_a 
array([0, 1, 2, 3, 4]) 
>>> type(np_a) 
<class 'numpy.ndarray') 

>>> py_a = list(range(5)) 
>>> py_a 
[0, 1, 2, 3, 4] 
>>> type(py_a) 
<class 'list'> 

# The numerical answer (10) is the same for the following sums: 
>>> type(np.sum(np_a)) 
<class 'numpy.int32'> 
>>> type(sum(np_a)) 
<class 'numpy.int32'> 
>>> type(np.sum(py_a)) 
<class 'numpy.int32'> 
>>> type(sum(py_a)) 
<class 'int'> 

編輯:我想我實際的問題,這裏將使用numpy.sum的Python整數列表上是比任何使用Python的sum更快?

此外,使用Python整數與標量numpy.int32的含義(包括性能)是什麼?例如,對於a += 1,如果a的類型是Python整數或numpy.int32,那麼是否存在行爲或性能差異?我很好奇,如果使用NumPy標量數據類型(如numpy.int32)來獲得在Python代碼中添加或減少很多值的速度更快。

爲了澄清,我正在進行生物信息學模擬,其中部分由摺疊多維numpy.ndarray組成的單個標量和然後另外處理。我正在使用Python 3.2和NumPy 1.6。

在此先感謝!

回答

42

我很好奇和計時。對於numpy數組,numpy.sum似乎要快得多,但在列表上要慢得多。

import numpy as np 
import timeit 

x = range(1000) 
# or 
#x = np.random.standard_normal(1000) 

def pure_sum(): 
    return sum(x) 

def numpy_sum(): 
    return np.sum(x) 

n = 10000 

t1 = timeit.timeit(pure_sum, number = n) 
print 'Pure Python Sum:', t1 
t2 = timeit.timeit(numpy_sum, number = n) 
print 'Numpy Sum:', t2 

結果時x = range(1000)

Pure Python Sum: 0.445913167735 
Numpy Sum: 8.54926219673 

結果時x = np.random.standard_normal(1000)

Pure Python Sum: 12.1442425643 
Numpy Sum: 0.303303771848 

我使用Python 2.7.2和1.6.1 numpy的

+0

+1,但是你難道沒有這些結果嗎? – dawg

+0

@drewk,是的,我確實有過它們。謝謝你指出這一點!固定。 – Akavall

+0

當你使用'np.array'時,'np.sum'會更快。但是如果你計算'np.sum(np.array對象)'和'sum(列表對象)',兩者的表現幾乎相同。 – xyres

5

Numpy應該快得多,特別是當你的數據已經是一個numpy數組時。

Numpy數組是一個標準C數組上的薄層。當numpy sum迭代這個時,它不會進行類型檢查,而且速度非常快。速度應該與使用標準C進行操作相當。

相比之下,使用python的總和,它必須首先將numpy數組轉換爲python數組,然後遍歷該數組。它必須進行一些類型檢查,並且通常會變得更慢。

python sum比numpy sum慢的確切數量沒有被很好地定義,因爲python sum將會是一個稍微優化的函數,與在python中編寫自己的sum函數相比。

+5

它不會'轉換'numpy數組 - 一個numpy數組已經可以在Python中迭代。另一方面,'numpy.sum'可能需要將一個列表轉換爲一個numpy數組,這將解釋@Akavall的計時結果。 –

+1

無論轉換髮生爲數組到數組還是通過類型化單個項目,您都會在某個級別轉換項目(從/到本機類型),這就是我試圖創建的點。 – Claris

3

需要注意的是Python的總和上多維numpy數組只會沿着第一個軸執行一個和:

sum(np.array([[[2,3,4],[4,5,6]],[[7,8,9],[10,11,12]]])) 
Out[47]: 
array([[ 9, 11, 13], 
     [14, 16, 18]]) 

np.sum(np.array([[[2,3,4],[4,5,6]],[[7,8,9],[10,11,12]]]), axis=0) 
Out[48]: 
array([[ 9, 11, 13], 
     [14, 16, 18]]) 

np.sum(np.array([[[2,3,4],[4,5,6]],[[7,8,9],[10,11,12]]])) 
Out[49]: 81 
1

這是對answer post above by Akavall的擴展。從該答案中可以看出np.sum對於np.array對象執行得更快,而sumlist對象執行得更快。若要擴展:

在運行np.sumnp.array對象比。sum對於一個list對象,它似乎是一對一對決。

# I'm running IPython 

In [1]: x = range(1000) # list object 

In [2]: y = np.array(x) # np.array object 

In [3]: %timeit sum(x) 
100000 loops, best of 3: 14.1 µs per loop 

In [4]: %timeit np.sum(y) 
100000 loops, best of 3: 14.3 µs per loop 

以上,sum微小位比np.array快,雖然有時我見過np.sum時序是14.1 µs,太。但主要是,它是14.3 µs