python中的for循环比matlab慢10倍

时间:2013-06-21 19:13:21

标签: python matlab for-loop

我在同一台机器上运行python 2.7和matlab R2010a,什么都不做,它给了我10倍的速度

我在网上看了,听说应该是同一个订单。 Python将进一步减慢,就像for循环中的语句和数学运算符一样

我的问题:这是现实吗?还是有其他方式让他们以相同的速度顺序?


这是python代码

import time

start_time = time.time()

for r in xrange(1000):

      for c in xrange(1000):

         continue

elapsed_time = time.time() - start_time

print 'time cost = ',elapsed_time

Output: time cost = 0.0377440452576

这是matlab代码

tic

for i = 1:1000

    for j = 1:1000

    end

end

toc

Output: Escaped time is 0.004200 seconds

4 个答案:

答案 0 :(得分:8)

发生这种情况的原因与JIT编译器有关,它正在优化MATLAB for循环。您可以使用feature accel offfeature accel on禁用/启用JIT加速器。禁用加速器时,时间会发生显着变化。

MATLAB with accel on:Elapsed time is 0.009407 seconds.

MATLAB with accel off:Elapsed time is 0.287955 seconds.

python:time cost = 0.0511920452118

因此,JIT加速器直接导致您注意到的加速。您应该考虑另一件事,这与您定义迭代索引的方式有关。在MATLAB和python这两种情况下,您都使用迭代器来定义循环。在MATLAB中,您可以通过添加方括号([])来创建实际值,而在python中,您使用range而不是xrange。进行这些更改时

% MATLAB
for i = [1:1000]
    for j = [1:1000]

# python
for r in range(1000):
  for c in range(1000):

时代成为

MATLAB with accel on:Elapsed time is 0.338701 seconds.

MATLAB with accel off:Elapsed time is 0.289220 seconds.

python:time cost = 0.0606048107147

最后一个考虑因素是你是否要在循环中添加一个快速计算。即t=t+1。然后时间成为

MATLAB with accel on:Elapsed time is 1.340830 seconds.

MATLAB with accel off:Elapsed time is 0.905956 seconds.(Yes off更快)

python:time cost = 0.147221088409

我认为这里的道德观点是,开环即用的for循环的计算速度与极其简单的循环相当,具体取决于具体情况。然而,python中还有其他一些数值工具可以显着加快速度,numpy和PyPy到目前为止已经提出。

答案 1 :(得分:3)

基本的Python实现CPython并不意味着超级快速。如果您需要高效的matlab风格的数值操作,请使用the numpy package或专为快速工作而设计的Python实现,例如PyPy甚至Cython。 (在C中编写Python扩展,当然速度非常快,也是一种可能的解决方案,但在这种情况下,您也可以使用numpy并省去自己的努力。)

答案 2 :(得分:2)

如果Python执行性能对您至关重要,您可以查看PyPy

我做了你的测试:

import time
for a in range(10):
    start_time = time.time()
    for r in xrange(1000):
        for c in xrange(1000):
            continue

    elapsed_time = time.time()-start_time
    print elapsed_time

使用标准Python 2.7.3,我得到:

0.0311839580536
0.0310959815979
0.0309510231018
0.0306520462036
0.0302460193634
0.0324130058289
0.0308878421783
0.0307397842407
0.0304911136627
0.0307500362396

然而,使用PyPy 1.9.0(对应于Python 2.7.2),我得到:

0.00921821594238
0.0115230083466
0.00851202011108
0.00808095932007
0.00496387481689
0.00499391555786
0.00508499145508
0.00618195533752
0.005126953125
0.00482988357544

PyPy的加速真的令人惊叹,当它的JIT编译器优化超过它们的成本时真的变得可见。这也是我引入额外for循环的原因。对于此示例,绝对不需要修改代码。

答案 3 :(得分:0)

这只是我的看法,但我认为过程要复杂一些。基本上,Matlab是C的优化层,因此通过适当地初始化矩阵和最小化函数调用(在Matlab中避免使用“。”对象之类的运算符),您可以获得截然不同的结果。考虑具有余弦函数的波形发生器的以下简单示例。在实际的调试会话中,Matlab时间= 0.15秒,在实际的调试会话(Spyder)中,Python时间= 25秒,因此Python变慢了166倍。直接由Python 3.7.4运行。机器的时间大约是5秒,因此仍然是不可忽略的33x。

MATLAB:

AW(1,:) = [800 , 0    ]; % [amp frec]
AW(2,:) = [300 , 4E-07]; 
AW(3,:) = [200 , 1E-06];
AW(4,:) = [ 50 , 4E-06];
AW(5,:) = [ 30 , 9E-06];
AW(6,:) = [ 20 , 3E-05];
AW(7,:) = [ 10 , 4E-05];
AW(8,:) = [  9 , 5E-04];
AW(9,:) = [  7 , 7E-04];
AW(10,:)= [  5 , 8E-03];

phas    = 0

tini    = -2*365 *86400; % 2 years backwards in seconds
dt      = 200;        % step, 200 seconds
tfin    = 0;          % present
vec_t   = ( tini: dt: tfin)'; % vector_time

nt      = length(vec_t);
vec_t   = vec_t - phas;
wave    = zeros(nt,1);

for it = 1:nt
    suma = 0;
    t    = vec_t(it,1);
    for iW = 1:size(AW,1)
        suma = suma + AW(iW,1)*cos(AW(iW,2)*t);
    end
    wave(it,1) = suma;
end

PYTHON:

import numpy as np

AW      = np.zeros((10,2))
AW[0,:] = [800 , 0.0]
AW[1,:] = [300 , 4E-07]; # [amp frec]
AW[2,:] = [200 , 1E-06];
AW[3,:] = [ 50 , 4E-06];
AW[4,:] = [ 30 , 9E-06];
AW[5,:] = [ 20 , 3E-05];
AW[6,:] = [ 10 , 4E-05];
AW[7,:] = [  9 , 5E-04];
AW[8,:] = [  7 , 7E-04];
AW[9,:] = [  5 , 8E-03];

phas    = 0

tini    = -2*365 *86400 # 2 years backwards
dt      = 200
tfin    = 0           # present
nt      = round((tfin-tini)/dt) + 1 
vec_t   = np.linspace(tini,tfin1,nt) - phas

wave    = np.zeros((nt))

for it in range(nt):
    suma   = 0
    t      = vec_t[fil]
    for iW in range(np.size(AW,0)):
        suma = suma + AW[iW,0]*np.cos(AW[iW,1]*t)
    #endfor iW
    wave[it] = suma
#endfor it

要处理Python中的这些方面,我建议直接编译为可执行文件,以将可能损害项目的数字部分二进制化(或将C或Fortran转换为可执行文件,然后由Python调用)。当然,其他建议也值得赞赏。