2013-06-21 31 views
1

我有以下瓶頸,想知道是否有人可以建議加速它的方法。爲python循環加速求和

我有三個列表x,y,z長度爲N。我申請以下summation

def abs_val_diff(x1, x2, x3, y1, y2, y3): 
    """ Find the absolute value of the difference between x and y """ 
    return py.sqrt((x1 - y1) ** 2.0 + (x2 - y2) ** 2.0 + (x3 - y3) ** 2.0) 

R = 0.1 
sumV = 0.0 
for i in xrange(N): 
    for j in xrange(i + 1, N): 
     if R > abs_val_diff(x[i], y[i], z[i], 
          x[j], y[j], z[j]): 
       sumV += 1.0 

我一直在使用numpy的陣列試過,但無論是我做錯了什麼或有大約一個任何想法,將不勝感激的2.

因素的速度降低。

+0

我沒有看到與Cython的關係。我刪除標籤... –

+0

我曾考慮過使用Cython來加速計算。無論哪種方式都沒有關係。 – Greg

回答

3

我相信你可以通過做下面的事情來更有效地利用numpy。做一個小的修改,以你的函數使用numpy.sqrt:

import numpy as np 

def abs_val_diff(x1, x2, x3, y1, y2, y3): 
    """ Find the absolute value of the difference between x and y """ 
    return np.sqrt((x1 - y1) ** 2.0 + (x2 - y2) ** 2.0 + (x3 - y3) ** 2.0) 

然後與全陣列撥打:

res = abs_val_diff(x[:-1],y[:-1],z[:-1],x[1:],y[1:],z[1:]) 

然後,因爲你每場比賽加1,你可以簡單地取查詢結果產生的數組長度:

sumV = len(res[R>res]) 

這讓numpy處理迭代。希望這對你有用

+0

謝謝,它需要稍作修改,因爲有兩個總結,但與鄧肯的答案相結合,這提供了10倍加速:D謝謝 – Greg

+2

做'np.nonzero(R> res)'' ,而不是提取滿足條件的值並查看其「len」的數組。 – Jaime

0

事實證明,列表解析通常比Python中的顯式循環更快,因爲它們可以編譯爲更高效的字節碼。我不知道這是否會幫助你,但嘗試是這樣的:

sumV = sum((1.0 for j in xrange(1+1, N) for i in xrange(N) if R > abs_val_diff(x[i], y[i], z[i], x[j], y[j], z[j]))) 

是的,它看起來絕對殘暴,但你去那裏。更多信息可以發現herehere

2

是否有任何理由,你實際上需要在你的函數的平方根?如果你對結果所做的只是將其與限制進行比較,爲什麼不只是比較兩方?

def abs_val_diff_squared(x1, x2, x3, y1, y2, y3): 
    """ Find the square of the absolute value of the difference between x and y """ 
    return (x1 - y1) ** 2.0 + (x2 - y2) ** 2.0 + (x3 - y3) ** 2.0 

R = 0.1 
R_squared = R * R 
sumV = 0.0 
for i in xrange(N): 
    for j in xrange(i + 1, N): 
     if R_squared > abs_val_diff_squared(x[i], y[i], z[i], 
          x[j], y[j], z[j]): 
       sumV += 1.0 

我也覺得,就必須有從數據整理成類似的octtree上漲,所以你只需要看看附近的點,而不是比較反對一切一切都大得多的儲蓄,但是這是我的知識之外。

+0

使用時間,這似乎在幾秒鐘內,感謝輸入。 – Greg

+0

嗨鄧肯,對不起,我一直在改變答案,我不知道你只能選擇一個答案。我想勾選你和blazetopher結合這已經解決了我的問題。祝一切順利 – Greg