Python 为什么是numpy';s exp比Matlab慢?如何使它更快?

Python 为什么是numpy';s exp比Matlab慢?如何使它更快?,python,matlab,performance,numpy,Python,Matlab,Performance,Numpy,我有一个非常简单的例子,它显示NumPy的np.exp比Matlab慢10倍左右。如何提高Python的速度?我运行的是32位Python 2.7,NumPy版本1.11.3,NumPy使用的是MKL blas和lapack库 而且,时间上的差异如此之大,以至于我认为计时机制没有产生太大的影响 Python中的代码示例: import numpy as np import timeit setup='import numpy as np; import numexpr as ne; n=100

我有一个非常简单的例子,它显示NumPy的
np.exp
比Matlab慢10倍左右。如何提高Python的速度?我运行的是32位Python 2.7,NumPy版本1.11.3,NumPy使用的是MKL blas和lapack库

而且,时间上的差异如此之大,以至于我认为计时机制没有产生太大的影响

Python中的代码示例:

import numpy as np
import timeit

setup='import numpy as np; import numexpr as ne; n=100*1000; a = np.random.uniform(size=n)'
time = timeit.timeit('b=np.exp(a)', setup=setup, number=1000)
print 'Time for 1000 (np.exp): ',time
time = timeit.timeit('b=ne.evaluate("exp(a)")', setup=setup, number=1000)
print 'Time for 1000 (numexpr): ',time
结果:

Time for 1000 (np.exp):  2.25906916167
Time for 1000 (numexpr):  0.591470532849
在Matlab中:

a = rand([100*1000,1]);
times = [];
for i=1:1000,
    tic
    b = exp(a);
    t=toc;
    times(i) = t;
end

fprintf('Time for 1000: %f\n',sum(times));
导致:

Time for 1000: 0.268527

为了提高性能,特别是在大型数据集上,我们可以利用这些超越函数-

import numexpr as ne

b = ne.evaluate('exp(a)')
标杆管理 对于适当的基准测试,我将使用-

设置#1

MATLAB:

>> a = rand([100*1000,1]);
>> func = @() exp(a);
>> timeit(func)
ans =
    0.0013 % That's 1.3 m-sec
>> a = rand([1000*10000,1]);
>> func = @() exp(a);
>> timeit(func)
ans =
    0.0977  % That's 97 m-sec
大小相同的数据集上的NumPy:

In [417]: n=100*1000
     ...: a = np.random.uniform(size=n)
     ...: 

In [418]: %timeit np.exp(a)
1000 loops, best of 3: 1.5 ms per loop

In [419]: %timeit ne.evaluate('exp(a)')
1000 loops, best of 3: 397 µs per loop
因此,

MATLAB  : 1.3 m-sec
NumPy   : 1.5 m-sec
Numexpr : 0.4 m-sec
MATLAB  :  97 m-sec
NumPy   : 154 m-sec
Numexpr :  36 m-sec
设置#2

MATLAB:

>> a = rand([100*1000,1]);
>> func = @() exp(a);
>> timeit(func)
ans =
    0.0013 % That's 1.3 m-sec
>> a = rand([1000*10000,1]);
>> func = @() exp(a);
>> timeit(func)
ans =
    0.0977  % That's 97 m-sec
努比:

In [412]: n=1000*10000
     ...: a = np.random.uniform(size=n)
     ...: 

In [413]: %timeit np.exp(a)
10 loops, best of 3: 154 ms per loop

In [414]: %timeit ne.evaluate('exp(a)')
10 loops, best of 3: 36.5 ms per loop
因此,

MATLAB  : 1.3 m-sec
NumPy   : 1.5 m-sec
Numexpr : 0.4 m-sec
MATLAB  :  97 m-sec
NumPy   : 154 m-sec
Numexpr :  36 m-sec

tic toc进行适当的基准测试

这个问题中的基准测试的缺点是,我们在一个循环中得到了toc经过的时间,而这个循环没有运行足够的时间来给我们提供任何准确的时间。普遍接受的想法是,
toc
经过的计时必须至少接近
1
sec标记

因此,通过这些校正,可以使用
tic-toc
进行更精确的计时测试-

tic
for i=1:1000,
    b = exp(a);
end
t=toc;
timing = t./1000
这就产生了-

timing =
    0.0010

这与我们的
1.3 m-sec
timeit

非常接近。这里更大的问题是,为什么您的跑步速度比OPsMy time结果快1000倍,这是所有exp(a)跑步的总时间,而不是平均时间@Divakar——我添加了numexpr,这很好,也很有帮助,但我们仍然比Matlab慢2倍多。@SlaterTyranus实际上
%timeit
让我们平均运行1000次。OP是累积的,这不是平均值。不过,我不确定这是如何成为更大的问题的。“我们应该把重点放在加速上。”迪瓦卡哈,那就行了。降到3-4倍增量,这是一个更合理的硬件增量。@Isaaccher使用您信任的
setup='import numpy作为np;导入num..
code,然后使用我在文章末尾发布的tic-toc代码。对于三个版本:MATLAB、NumPy、Numexpr,您得到了什么结果?你能在问题中加上这一点吗,或者在评论中告诉我?timeit文档说没有多行字符串文字。我在猜测,如果设置部分作为timeit运行的一部分进行评估,那么您传递设置部分的方式。通过在python中模仿matlab中的tic/tock设置,您可以进行直接的苹果对苹果的比较。@SlaterTyranus:docs说
stmt
setup
不能包含多行字符串文字,并不是说它们本身不能跨越多行。我相信这是因为它用来调整多行输入缩进的
timeit
会破坏输入中的多行字符串文字。而且,就如何使其更快而言,这实际上与numpy无关,而与引擎盖下的lapack无关。如果你想改进它,那就是你要看的地方。是的,我把设置字符串改成了用分号分隔的单个字符串,同样的计时结果。@user2357112我的错误。在过去,我遇到了一些微妙的问题,无法从思想上解析输入字符串。