为什么numpy的exp比Matlab慢?如何使其更快?

Isa*_*her 3 python performance matlab 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*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
Run Code Online (Sandbox Code Playgroud)

结果是:

Time for 1000 (np.exp):  2.25906916167
Time for 1000 (numexpr):  0.591470532849
Run Code Online (Sandbox Code Playgroud)

在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));
Run Code Online (Sandbox Code Playgroud)

导致:

Time for 1000: 0.268527
Run Code Online (Sandbox Code Playgroud)

Div*_*kar 5

为了提高性能(尤其是在大型数据集上的性能),我们可以将numexpr模块用于此类先验功能-

import numexpr as ne

b = ne.evaluate('exp(a)')
Run Code Online (Sandbox Code Playgroud)

标杆管理

对于一个适当的基准,我会用timeit on MATLABNumPy's %timeit-

设置1

MATLAB:

>> a = rand([100*1000,1]);
>> func = @() exp(a);
>> timeit(func)
ans =
    0.0013 % That's 1.3 m-sec
Run Code Online (Sandbox Code Playgroud)

在相同大小的数据集上的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
Run Code Online (Sandbox Code Playgroud)

从而,

MATLAB  : 1.3 m-sec
NumPy   : 1.5 m-sec
Numexpr : 0.4 m-sec
Run Code Online (Sandbox Code Playgroud)

设置#2

MATLAB:

>> a = rand([1000*10000,1]);
>> func = @() exp(a);
>> timeit(func)
ans =
    0.0977  % That's 97 m-sec
Run Code Online (Sandbox Code Playgroud)

NumPy:

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
Run Code Online (Sandbox Code Playgroud)

从而,

MATLAB  :  97 m-sec
NumPy   : 154 m-sec
Numexpr :  36 m-sec
Run Code Online (Sandbox Code Playgroud)

正确的基准测试 tic-toc

问题中基准测试的错误在于,我们在一个循环中获得了toc过去的计时,该循环没有足够的时间运行,无法为我们提供任何准确的计时。普遍接受的想法是,toc经过的时间必须至少接近1秒标记。

因此,通过这些更正,更准确的时序测试tic-toc将是-

tic
for i=1:1000,
    b = exp(a);
end
t=toc;
timing = t./1000
Run Code Online (Sandbox Code Playgroud)

这产生-

timing =
    0.0010
Run Code Online (Sandbox Code Playgroud)

这是接近我们1.3 m-sectimeit