首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在数字化的例子中,numpy比matlab慢得多?

为什么在数字化的例子中,numpy比matlab慢得多?
EN

Stack Overflow用户
提问于 2012-02-25 13:28:48
回答 4查看 4.9K关注 0票数 15

我正在比较numpy与matlab的性能,在一些情况下,我观察到numpy要慢得多(索引、对数组的简单操作,如绝对值、乘法、和等)。让我们看一下下面的示例,这个例子令人吃惊,它涉及数字化函数(我计划使用这个函数来同步时间戳):

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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库作为扩展):

代码语言:javascript
运行
复制
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倍)。

所以问题是:

  • 为什么numpy.digitize这么慢?这个函数不应该用编译和优化的代码编写吗?
  • 为什么我自己的数字化版本比numpy.digitize快得多,但仍然比Matlab慢(我很有信心我使用最快的算法,因为我假设输入已经排序了)?

我正在使用Fedora 16,我最近安装了ATLAS和LAPACK库(但是性能发生了如此大的变化)。我应该重建一下吗?我不确定numpy的安装是否使用适当的库来获得最大的速度,也许Matlab正在使用更好的库。

更新

根据到目前为止的答案,我想强调的是,如果有人(在本例中是我)不关心直方图,那么Matlab函数组是,而不是与numpy.histogram等效的。我需要hisc的第二个输出,它是从输入值到提供的输入回收箱的索引的映射。这样的输出由数字和搜索排序的numpy函数提供。正如其中一个答案所说,搜索排序比数字化快得多。然而,按因子2计算,搜索排序仍然比Matlab慢。

代码语言:javascript
运行
复制
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秒

现在的问题是:

  1. 如果有一个等价的函数numpy.digitize,它的速度是的280倍,那么拥有的意义是什么?
  2. 为什么Matlab函数组(它也提供numpy.searchsorted的输出)比numpy.searchsorted快2倍
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-25 15:49:12

首先,让我们来看看为什么numpy.digitize速度慢。如果您的回收箱是单调的,那么根据回收箱是不减少的还是不增加的,调用这些函数之一(代码在numpy git中的numpy/lib/src/_compiled_base.c中找到):

代码语言:javascript
运行
复制
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还假设认为回收箱是单调的、不递减的。

票数 21
EN

Stack Overflow用户

发布于 2012-02-25 14:02:09

我无法回答为什么numpy.digitize()这么慢--我可以在我的机器上确认你的时间。

函数numpy.searchsorted()numpy.digitize()做的基本相同,但效率很高。

代码语言:javascript
运行
复制
ind = np.searchsorted(y, scale, "right")

在我的机器上花费大约0.15秒,并给出与您的代码完全相同的结果。

请注意,您的Matlab代码所做的事情不同于这两个函数--它相当于numpy.histogram()

票数 6
EN

Stack Overflow用户

发布于 2012-02-25 16:22:14

在回答问题之前,需要解决以下几个子问题:

  1. 为了获得更可靠的结果,您应该运行测试的几次迭代,并对其结果进行平均值。这将在某种程度上消除与算法无关的启动效果。此外,尝试使用更大的数据来达到同样的目的。
  2. 跨框架使用相同的算法。在这里的其他答复中已经提到了这一点。
  3. 请确保算法非常相似。他们如何利用系统资源?如何在内存上进行迭代?如果(仅举一个例子) Matlab算法使用repmat而numpy不使用,则比较是不公平的。
  4. 相应的框架如何并行化?这可能与您的单个计算机/处理器配置相连接。Matlab对一些(但目前还不是全部)内置函数进行并行化。我不知道numpy/CPython。
  5. 使用内存分析器可以从性能的角度了解这两个实现是如何运行的。

之后(这只是猜测),我们可能会发现,numpy的行为通常比Matlab慢。因此,这里的许多问题得出了同样的结论。一种解释可能是,Matlab可以更容易地优化数组访问,因为它不需要考虑整个通用对象集合(如CPython)。对数学阵列的要求远低于一般阵列的要求。另一方面,numpy确实利用了CPython,它必须为完整的python库提供服务,而不仅仅是numpy。然而,根据这个比较试验 (和其他许多) Matlab仍然是相当慢的.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9444409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档