2010-01-01 67 views
4

我一直在做一些性能測試,以提高我寫的寵物項目的性能。這是一個非常緊湊的應用程序,所以我一直在玩Numpy作爲提高計算性能的一種方式。差numpy.cross()性能

然而,從下面的性能測試結果相當令人吃驚....

測試源代碼(更新測試用例吊裝和批量提交)

import timeit 

numpySetup = """ 
import numpy 
left = numpy.array([1.0,0.0,0.0]) 
right = numpy.array([0.0,1.0,0.0]) 
""" 

hoistSetup = numpySetup +'hoist = numpy.cross\n' 

pythonSetup = """ 
left = [1.0,0.0,0.0] 
right = [0.0,1.0,0.0] 
""" 

numpyBatchSetup = """ 
import numpy 

l = numpy.array([1.0,0.0,0.0]) 
left = numpy.array([l]*10000) 

r = numpy.array([0.0,1.0,0.0]) 
right = numpy.array([r]*10000) 
""" 

pythonCrossCode = """ 
x = ((left[1] * right[2]) - (left[2] * right[1])) 
y = ((left[2] * right[0]) - (left[0] * right[2])) 
z = ((left[0] * right[1]) - (left[1] * right[0])) 
""" 

pythonCross = timeit.Timer(pythonCrossCode, pythonSetup) 
numpyCross = timeit.Timer ('numpy.cross(left, right)' , numpySetup) 
hybridCross = timeit.Timer(pythonCrossCode, numpySetup) 
hoistCross = timeit.Timer('hoist(left, right)', hoistSetup) 
batchCross = timeit.Timer('numpy.cross(left, right)', numpyBatchSetup) 

print 'Python Cross Product : %4.6f ' % pythonCross.timeit(1000000) 
print 'Numpy Cross Product : %4.6f ' % numpyCross.timeit(1000000) 
print 'Hybrid Cross Product : %4.6f ' % hybridCross.timeit(1000000) 
print 'Hoist Cross Product : %4.6f ' % hoistCross.timeit(1000000) 
# 100 batches of 10000 each is equivalent to 1000000 
print 'Batch Cross Product : %4.6f ' % batchCross.timeit(100) 

原始結果

Python Cross Product : 0.754945 
Numpy Cross Product : 20.752983 
Hybrid Cross Product : 4.467417 

最終結果

Python Cross Product : 0.894334 
Numpy Cross Product : 21.099040 
Hybrid Cross Product : 4.467194 
Hoist Cross Product : 20.896225 
Batch Cross Product : 0.262964 

不用說,這不是結果我的預期。純Python版本比Numpy執行速度快了近30倍。其他測試中的Numpy性能比Python相當好(這是預期的結果)。爲什麼NumPy的是在這種情況下進行如此糟糕

  • 誰能解釋:

    所以,我有兩個相關的問題?

  • 有什麼我可以做的,以解決它?

回答

6

用更大的陣列試試這個。我認爲這裏調用numpy方法的代價超過了Python版本所需的簡單的幾個列表訪問。如果你處理更大的陣列,我想你會看到numpy的大勝。

+0

在這種特殊情況下,3個分量數組(x,y,z座標)是最常見的情況。也有點奇怪的是,即使從numpy數組中讀取,Python代碼仍然更快。如果是通話開銷,我預計它會比純粹的NumPy解決方案慢得多。 – 2010-01-01 08:39:01

+0

@Adam:但是通過從numpy的數組中讀取數據,可以節省調用'cross'函數本身的開銷,這是一個動態加載的擴展,所以它至少經歷了幾次指針。對於這樣短的陣列,它確實很有意義,因爲它是一個微調優化,可以將調用展開爲'cross' – 2010-01-01 08:42:23

+0

我剛剛添加了一個測試用例,我將這些陣列分配在一起,並且看到了相當大的性能提升。所以我會說頭頂理論是正確的。看起來如果我想用Numpy來提升性能,我需要找到一種將這些操作組合在一起的方法。 – 2010-01-02 02:57:07

0

優秀的文章!我認爲比較並不公平。批交叉產品給出一個包含所有向量的交叉產品的數組,而Python交叉產品每次只給出一個向量。如果您需要一次計算所有交叉產品,當然Batch更好,但是如果您需要分別計算每個交叉產品,則應包括訪問該陣列的開銷。另外,如果交叉產品,如果以前的交叉產品的功能批處理實施應該被修改。