【发布时间】:2012-03-15 17:01:34
【问题描述】:
我正在比较 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
的相同示例 Matlabscale=[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 时,我实现了自己的 digitize 版本(使用 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 秒
由于我的 digitize 版本假设输入都是单调的,所以有一点作弊,这可以解释为什么它甚至比 Matlab 更快。但是,对大小为 1e+6 的数组进行排序需要 0.16 秒(使用 numpy.sort),因此与 Matlab 函数 histc.
所以问题是:
- 为什么 numpy.digitize 这么慢?这个函数不应该用编译和优化的代码编写吗?
- 为什么我自己的 digitize 版本比 numpy.digitize 快得多,但仍然比 Matlab 慢(鉴于我假设输入已经排序,我很有信心使用最快的算法)?
我正在使用 Fedora 16,并且我最近安装了 ATLAS 和 LAPACK 库(但性能发生了如此大的变化)。我应该重建numpy吗?我不确定我安装的 numpy 是否使用适当的库来获得最大速度,也许 Matlab 正在使用更好的库。
更新
根据目前的答案,我想强调一下,如果有人,Matlab 函数 histc 不等同于 到 numpy.histogram (在这种情况下像我一样)不关心直方图。我需要 hisc 的第二个输出,它是从输入值到所提供输入箱的索引的映射。这样的输出由 numpy 函数 digitize 和 searchsorted 提供。正如其中一个答案所说,searchsorted 比 digitize 快得多。然而,searchsorted 仍然比 Matlab 慢 2 倍:
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 秒
所以现在的问题是:
如果有一个等效的函数 numpy.searchsorted,那么拥有 numpy.digitize 是什么意思,它快了 280 倍 ?
为什么Matlab函数histc(也提供numpy.searchsorted的输出)比快2倍 >numpy.searchsorted?
【问题讨论】:
-
您能否编辑您的问题以包含您的 C++ 版本的 digitize?很难说为什么你的版本在没有看到它的情况下可能与 numpy 中的不同......
-
我看不出所使用的任何功能与 ATLAS 甚至 LAPACK 有什么关系。这些库不会在这里使用,因此不会影响结果。
标签: python performance matlab numpy