我正在比较 numpy 和 matlab 的性能,在几种情况下,我观察到numpy明显较慢(索引、数组上的简单操作,如绝对值、乘法、求和等)。让我们看下面这个例子,它有点惊人,涉及到函数digitize(我打算用它来同步时间戳):
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秒
现在让我们尝试使用等效函数histc来执行相同的例子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库实现了自己的digitize版本:
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秒。我的digitize版本存在一些欺骗性,因为它假定输入都是单调的,这可能解释了为什么它甚至比Matlab更快。然而,对一个大小为1e+6的数组进行排序需要0.16秒(使用numpy.sort),因此我的函数的表现比Matlab函数histc差(约为1.6倍)。
问题是:
1. 为什么numpy.digitize如此缓慢?难道这个函数不应该是用编译和优化代码编写的吗? 2. 为什么我的digitize版本比numpy.digitize快得多,但仍然比Matlab慢(我非常有信心,我使用的是最快的算法,因为我假设输入已经排序)?
我正在使用Fedora 16,最近安装了ATLAS和LAPACK库(但性能没有改变)。也许我应该重新构建numpy?我不确定我安装的numpy是否使用适当的库以获得最大速度,也许Matlab正在使用更好的库。
更新:
根据迄今为止的答案,我想强调,如果某人(像我一样)不关心直方图,则Matlab函数histc与numpy.histogram不等价。我需要hisc的第二个输出,即将输入值映射到提供的输入bin的索引。numpy函数digitize和searchsorted提供了这样的输出。正如其中一个答案所说,searchsorted比digitize快得多。然而,searchsorted仍然比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秒
现在的问题是:
如果有一个速度快280倍的等效函数numpy.searchsorted,那么为什么还需要numpy.digitize?
为什么Matlab函数histc(也提供numpy.searchsorted的输出)比numpy.searchsorted 快2倍?