我正在比较numpy与matlab的性能,在一些情况下,我观察到numpy要慢得多(索引、对数组的简单操作,如绝对值、乘法、和等)。让我们看一下下面的示例,这个例子令人吃惊,它涉及数字化函数(我计划使用这个函数来同步时间戳):
import numpy as np
import time
scale=np.arange(1,1e+6+1)
y=np.arange(1,1e+6+1,10)
t1=time.time()
ind=np.digitize(scale,y)
t2=time.time()
print 'Time passed is %2.2f seconds' %(t2-t1)结果是:
时间过了55.91秒
现在让我们使用等效函数来尝试相同的示例Matlab
scale=[1:1e+6];
y=[1:10:1e+6];
tic
[N,bin]=histc(scale,y);
t=toc;
display(['Time passed is ',num2str(t), ' seconds'])结果是:
时间过了0.10237秒
这是的560倍快!
当我学习用C++扩展Python时,我实现了自己的数字化版本(使用boost库作为扩展):
import analysis # my C++ module implementing digitize
t1=time.time()
ind2=analysis.digitize(scale,y)
t2=time.time()
print 'Time passed is %2.2f seconds' %(t2-t1)
np.all(ind==ind2) #ok结果是:
时间过了0.02秒
有一点作弊,因为我的数字化版本假设输入都是单调的,这也许可以解释为什么它比Matlab还要快。但是,对大小为1e+6的数组进行排序需要0.16秒(使用numpy.sort),因此,与Matlab函数组相比,我的函数的性能更差(约为1.6倍)。
所以问题是:
我正在使用Fedora 16,我最近安装了ATLAS和LAPACK库(但是性能发生了如此大的变化)。我应该重建一下吗?我不确定numpy的安装是否使用适当的库来获得最大的速度,也许Matlab正在使用更好的库。
更新
根据到目前为止的答案,我想强调的是,如果有人(在本例中是我)不关心直方图,那么Matlab函数组是,而不是与numpy.histogram等效的。我需要hisc的第二个输出,它是从输入值到提供的输入回收箱的索引的映射。这样的输出由数字和搜索排序的numpy函数提供。正如其中一个答案所说,搜索排序比数字化快得多。然而,按因子2计算,搜索排序仍然比Matlab慢。
t1=time.time()
ind3=np.searchsorted(y,scale,"right")
t2=time.time()
print 'Time passed is %2.2f seconds' %(t2-t1)
np.all(ind==ind3) #ok结果是
时间过了0.21秒
现在的问题是:
发布于 2012-02-25 15:49:12
首先,让我们来看看为什么numpy.digitize速度慢。如果您的回收箱是单调的,那么根据回收箱是不减少的还是不增加的,调用这些函数之一(代码在numpy git中的numpy/lib/src/_compiled_base.c中找到):
static npy_intp
incr_slot_(double x, double *bins, npy_intp lbins)
{
npy_intp i;
for ( i = 0; i < lbins; i ++ ) {
if ( x < bins [i] ) {
return i;
}
}
return lbins;
}
static npy_intp
decr_slot_(double x, double * bins, npy_intp lbins)
{
npy_intp i;
for ( i = lbins - 1; i >= 0; i -- ) {
if (x < bins [i]) {
return i + 1;
}
}
return 0;
}正如你所看到的,它在做一个线性搜索。线性搜索要比二进制搜索慢得多,所以有你的答案,为什么它是慢的。我会在numpy跟踪器上打开一张票。
其次,我认为Matlab实际上比您的C++代码慢,因为Matlab还假设认为回收箱是单调的、不递减的。
发布于 2012-02-25 14:02:09
我无法回答为什么numpy.digitize()这么慢--我可以在我的机器上确认你的时间。
函数numpy.searchsorted()与numpy.digitize()做的基本相同,但效率很高。
ind = np.searchsorted(y, scale, "right")在我的机器上花费大约0.15秒,并给出与您的代码完全相同的结果。
请注意,您的Matlab代码所做的事情不同于这两个函数--它相当于numpy.histogram()。
发布于 2012-02-25 16:22:14
在回答问题之前,需要解决以下几个子问题:
之后(这只是猜测),我们可能会发现,numpy的行为通常比Matlab慢。因此,这里的许多问题得出了同样的结论。一种解释可能是,Matlab可以更容易地优化数组访问,因为它不需要考虑整个通用对象集合(如CPython)。对数学阵列的要求远低于一般阵列的要求。另一方面,numpy确实利用了CPython,它必须为完整的python库提供服务,而不仅仅是numpy。然而,根据这个比较试验 (和其他许多) Matlab仍然是相当慢的.
https://stackoverflow.com/questions/9444409
复制相似问题