2011-07-20 114 views
3

我正在用NumPy做一些計算,通過一個大盒子和一個小盒子之間的Aperture找到Y截距。我在大箱子裏有超過100.000個粒子,在小箱子裏有大約1000個。這需要花費很多時間。所有self.YD,self.XD都是我正在成倍增長的非常大的數組。計算 - numpy python bug

PS:ind是需要相乘的值的索引。在我的代碼之前,我有一個非零的條件。

任何想法如何以更簡單的方式做這個計算?

YD_zero = self.oldYD[ind] - ((self.oldYD[ind]-self.YD[ind]) * self.oldXD[ind])/(self.oldXD[ind]-self.XD[ind]) 

謝謝!

UPDATE

會用乘法,除法,減法和numpy的所有的東西。讓它更快? 或者如果我可以分割計算。例如。

首先做到這一點:

YD_zero = self.oldYD[ind] - ((self.oldYD[ind]-self.YD[ind])*self.oldXD[ind]) 

再下一行是:

YD_zero /= (self.oldXD[ind]-self.XD[ind]) 

任何建議?

更新2

我一直在試圖弄清楚這一點,在有一段時間了,但沒有太大的進展。我擔心的是分母:

self.oldXL[ind]-self.XL[ind] == 0 

我得到了一些奇怪的結果。

另一件事是非零功能。我一直在測試它一段時間。有人可以告訴我它幾乎和在Matlab中找到的一樣嗎

+0

是精密顯著的損失,如果你嘗試修剪點套? – Wok

+0

我需要有非常準確的數據。 –

+0

更簡單,你的意思是在更少的CPU週期? –

回答

2

由於所有的計算都是按照元素進行的,因此應該很容易重寫Cython中的表達式。這樣可以避免在執行oldYD-YD等時創建的所有非常大的臨時數組。

另一種可能性是numexpr

+0

如何將兩個數組與Numexpr或Cython相乘?你寧願建議Cython或Numexpr? –

+0

@theSun:關於乘法的具體問題是什麼引起了混淆?至於'Cython'和'numexpr',後者應該更容易正確。但是,我個人只使用前者,所以'numexpr'周圍可能存在一些我不知道的細節。 – NPE

3

也許我得到了棒的錯誤結局,但在Numpy中,您可以執行向量化計算。卸下封閉while環,只是執行這個...

YD_zero = self.oldYD - ((self.oldYD - self.YD) * self.oldXD)/(self.oldXD - self.XD)

應該會快很多。

更新:迭代求根使用牛頓迭代法...

unconverged_mask = np.abs(f(y_vals)) > CONVERGENCE_VALUE: 
while np.any(unconverged_mask): 
    y_vals[unconverged_mask] = y_vals[unconverged_mask] - f(y_vals[unconverged_mask])/f_prime(y_vals[unconverged_mask]) 
    unconverged_mask = np.abs(f(y_vals)) > CONVERGENCE_VALUE: 

這個代碼僅是說明性的,但它顯示瞭如何使用向量化代碼的任何功能f應用迭代過程,你可以找到f_prime的衍生物。unconverged_mask意味着當前迭代的結果將只應用於那些尚未收斂的值。

請注意,在這種情況下,不需要迭代,因爲我們正在處理直線,牛頓 - 拉夫遜將在第一次迭代中給出正確的答案。你有什麼是一個確切的解決方案。

二更新

好了,你不使用牛頓迭代。要一氣呵成計算YD_zero(y軸截距),你可以使用,

YD_zero = YD + (XD - X0) * dYdX

其中dYdX是梯度,這似乎是,你的情況,

dYdX = (YD - oldYD)/(XD - oldXD)

我假定XDYD是粒子的當前x,y值,oldXDoldYD是粒子的先前x,y值,並且X0是孔的x值URE。

仍然不完全清楚爲什麼你必須迭代所有的粒子,Numpy可以一次完成所有粒子的計算。

+0

如果您對它進行了矢量化,它還允許您稍後移動到GPU,如果您確實需要速度。 –

+0

我做了矢量化,但我在循環中有很多其他的東西。我認爲這比其他事情花費的時間更長。因爲我沒有這樣做,而且速度要快得多。 –

+1

我相信循環不在索引上,而是用於迭代牛頓算法。 – Wok

0

我肯定會去numexpr。我不知道numexpr能處理指標,但我敢打賭,下面的(或類似的東西)會的工作:

import numexpr as ne 

yold = self.oldYD[ind] 
y = self.YD[ind] 
xold = self.oldXD[ind] 
x = self.XD[ind] 
YD_zero = ne.evaluate("yold - ((yold - y) * xold)/(xold - x)")