繁体   English   中英

为什么numpy比数字化示例上的matlab慢得多?

[英]Why is numpy much slower than matlab on a digitize example?

我正在比较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库):

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函数histc相比,我的函数性能更差 (约1.6倍)。

所以问题是:

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

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

更新

基于到目前为止的答案,我想强调的是,如果有人(在这种情况下像我一样)不关心直方图,那么Matlab函数histc 不等于 numpy.histogram 我需要hisc的第二个输出,它是从输入值到提供的输入区的索引的映射。 这样的输出由数字化和搜索排序的numpy函数提供。 正如其中一个答案所说, searchsorted数字化要快得多。 但是,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秒

所以问题现在是:

  1. 什么是具有numpy.digitize如果有numpy.searchsorted同等功能是快280倍的意义吗?

  2. 为什么Matlab函数histc (也提供numpy.searchsorted的输出)比numpy.searchsorted 快2倍

首先,让我们看看为什么numpy.digitize很慢。 如果发现你的垃圾箱是单调的,那么根据垃圾箱是非减少还是不增加来调用其中一个函数(这个代码在numpy git repo中的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也假设这些分箱是单调非减少的。

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

该功能numpy.searchsorted()基本上做同样的事情numpy.digitize()但有效。

ind = np.searchsorted(y, scale, "right")

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

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

在问题得到解答之前,需要解决几个问题:

  1. 为了获得更可靠的结果,您应该运行多次测试并平均其结果。 这会以某种方式消除启动效果,这与算法没有任何关系。 此外,尝试使用更大的数据用于相同的目的。

  2. 在框架中使用相同的algortihms。 这已在其他答案中得到解决。

  3. 确保算法非常相似。 他们如何利用系统资源? 如何迭代内存? 如果(仅举例)Matlab算法使用repmat而numpy不会,则比较不公平。

  4. 相应的框架如何并行化? 这可能与您的个人计算机/处理器配置相关联。 Matlab确实并行化了一些(但不是全部)内置函数。 我不知道numpy / CPython。

  5. 使用内存分析器来了解这两种实现如何从性能角度出发。

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

我不认为你在numpy和matlab中比较相同的函数。 histc np.histogram ,相当于histcnp.histogram 我没有matlab进行比较,但是当我在我的机器上执行以下操作时:

In [7]: import numpy as np

In [8]: scale=np.arange(1,1e+6+1)

In [9]: y=np.arange(1,1e+6+1,10)

In [10]: %timeit np.histogram(scale,y)
10 loops, best of 3: 135 ms per loop

我得到的数字大约相当于你得到的histc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM