2011-07-20 115 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)")