幾年前,有人posted對活動狀態食譜作比較,三個python/NumPy函數;其中每個接受相同的參數並返回相同的結果,距離矩陣。爲什麼在這裏循環跳動索引?
其中兩個是從公開資料中獲得的;他們都是 - 或者他們似乎是我慣用的numpy代碼。創建距離矩陣所需的重複計算由numpy的優雅索引語法驅動。這裏是其中的一個:
from numpy.matlib import repmat, repeat
def calcDistanceMatrixFastEuclidean(points):
numPoints = len(points)
distMat = sqrt(sum((repmat(points, numPoints, 1) -
repeat(points, numPoints, axis=0))**2, axis=1))
return distMat.reshape((numPoints,numPoints))
使用一個循環(這顯然是一個很大的循環考慮到的只是1000的2D點的距離矩陣,有一萬個條目)第三創建距離矩陣。乍一看,這個函數在我看來像我在學習NumPy時編寫的代碼,我會先編寫NumPy代碼,然後逐行翻譯它。
活動狀態帖子發佈幾個月後,比較三者的性能測試結果在NumPy郵件列表上發佈並在thread中討論。
與事實上的循環功能顯著跑贏另外兩個:在線程
from numpy import mat, zeros, newaxis
def calcDistanceMatrixFastEuclidean2(nDimPoints):
nDimPoints = array(nDimPoints)
n,m = nDimPoints.shape
delta = zeros((n,n),'d')
for d in xrange(m):
data = nDimPoints[:,d]
delta += (data - data[:,newaxis])**2
return sqrt(delta)
一位與會者(凱爾·Mierle)提供一個理由,這可能是真實的:
我懷疑這會更快的原因是 它具有更好的地方性,完全完成一個相對較小的工作集上的計算,然後再轉到下一個工作集之一。一行 必須重複將可能較大的MxN陣列拉入處理器。
通過這張海報自己的帳戶,他的評論只是一個懷疑,似乎並沒有進一步討論。
有關如何解釋這些結果的其他想法?
特別是,有沒有一個有用的規則 - 關於什麼時候循環和何時索引 - 可以從這個例子中提取作爲編寫numpy代碼的指導?
對於那些不熟悉NumPy的人,或者沒有看過代碼的人,這種比較不是基於邊緣案例 - 如果是的話,這對我來說肯定不會那麼有趣。相反,這種比較涉及在矩陣計算中執行共同任務的功能(即,創建給定兩個前件的結果數組)。而且,每個函數都是由最常見的numpy內建插件組成的。
非常有幫助,謝謝。從我+1。 – doug 2010-08-19 07:31:20