为什么Python 3比Python 2慢很多? [英] Why is Python 3 is considerably slower than Python 2?

查看:211
本文介绍了为什么Python 3比Python 2慢很多?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图理解为什么在某些情况下Python 3与Python 2相比实际上要花费很多时间,以下是我从python 3.4到python 2.7进行验证的几种情况。

I've been trying to understand why Python 3 is actually taking much time compared with Python 2 in certain situations, below are few cases I've verified from python 3.4 to python 2.7.

注意:我已经经历过一些问题,例如为什么Python3中没有xrange函数?在python3中循环比python2慢得多相同的代码与Python2相比,Python3的速度要慢一些,但是我觉得我没有得到这个问题的真正原因。

Note: I've gone through some of the questions like Why is there no xrange function in Python3? and loop in python3 much slower than python2 and Same code slower in Python3 as compared to Python2, but I feel that I didn't get the actual reason behind this issue.

我已经尝试过代码来显示它如何发挥作用:

I've tried this piece of code to show how it is making difference:

MAX_NUM = 3*10**7

# This is to make compatible with py3.4.
try:
    xrange
except:
    xrange = range


def foo():
    i = MAX_NUM
    while i> 0:
        i -= 1

def foo_for():
    for i in xrange(MAX_NUM):
        pass

当我尝试使用py3.4和py2.7运行该程序时,我得到的结果低于

When I've tried running this programme with py3.4 and py2.7 I've got below results.

注意:这些统计信息来自具有 2.6Ghz 处理器的 64位计算机并在单个循环中使用 time.time()计算时间。

Note: These stats came through a 64 bit machine with 2.6Ghz processor and calculated the time using time.time() in single loop.

Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791

Output: Python 2.7
------------------
1.5131521225
0.475143909454

我真的不认为对 c或 xrange 从2.7到3.4,我知道 range 在py3.4中已经开始充当 xrange 的角色,但正如文档所述

I really don't think that there has been changes applied to while or xrange from 2.7 to 3.4, I know range has been started acting as to xrange in py3.4 but as documentation says


range()现在的行为类似于 xrange() 以前的行为是xcept可与任意大小的值一起使用。后者不再存在。

range() now behaves like xrange() used to behave, except it works with values of arbitrary size. The latter no longer exists.

这意味着从 xrange 更改为 range 非常类似于更改名称,但是可以使用任意值。

this means change from xrange to range is very much equal to a name change but working with arbitrary values.

我也验证了反汇编的字节码

I've verified disassembled byte code as well.

下面是函数 foo()的反汇编字节码:

Below is the disassembled byte code for function foo():

Python 3.4:
--------------- 

 13           0 LOAD_GLOBAL              0 (MAX_NUM)
              3 STORE_FAST               0 (i)

 14           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (i)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       34

 15          21 LOAD_FAST                0 (i)
             24 LOAD_CONST               2 (1)
             27 INPLACE_SUBTRACT
             28 STORE_FAST               0 (i)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

python 2.7
-------------

 13           0 LOAD_GLOBAL              0 (MAX_NUM)
              3 STORE_FAST               0 (i)

 14           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (i)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       34

 15          21 LOAD_FAST                0 (i)
             24 LOAD_CONST               2 (1)
             27 INPLACE_SUBTRACT    
             28 STORE_FAST               0 (i)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK           
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE        

下面是该函数的反汇编字节码 foo_for()

And below is the disassembled byte code for function foo_for():

Python: 3.4

 19           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_GLOBAL              1 (MAX_NUM)
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 GET_ITER
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

 20          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE


Python: 2.7
-------------

 19           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_GLOBAL              1 (MAX_NUM)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

 20          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK           
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE        

如果我们比较两个字节码,它们

If we compare both the byte codes they've produced the same disassembled byte code.

现在,我想知道从2.7到3.4的什么变化确实会导致给定代码段执行时间的巨大变化。

Now I'm wondering what change from 2.7 to 3.4 is really causing this huge change in execution time in the given piece of code.

推荐答案

不同之处在于 int 类型的实现。 Python 3.x仅使用任意大小的整数类型(在2.x中为 long ),而在Python 2.x中,其值最高为 sys .maxint 使用更简单的 int 类型,该类型在引擎盖下使用简单的C long

The difference is in the implementation of the int type. Python 3.x uses the arbitrary-sized integer type (long in 2.x) exclusively, while in Python 2.x for values up to sys.maxint a simpler int type is used that uses a simple C long under the hood.

一旦将循环限制为 long 个整数,Python 3.x是更快:

Once you limit your loops to long integers, Python 3.x is faster:

>>> from timeit import timeit
>>> MAX_NUM = 3*10**3
>>> def bar():
...     i = MAX_NUM + sys.maxsize
...     while i > sys.maxsize:
...         i -= 1
... 

Python 2:

>>> timeit(bar, number=10000)
5.704327821731567

Python 3:

>>> timeit(bar, number=10000)
3.7299320790334605

我用过 sys.maxsize 作为 sys.maxint 从Python 3中删除的,但整数值基本相同。

I used sys.maxsize as sys.maxint was dropped from Python 3, but the integer value is basically the same.

因此,Python 2的速度差异仅限于第一个(2 ** 63)-64位为1个整数,(2 ** 31)-32位系统为1个整数。

The speed difference in Python 2 is thus limited to the first (2 ** 63) - 1 integers on 64-bit, (2 ** 31) - 1 integers on 32 bit systems.

由于不能在 xrange()上使用 long 类型Python 2,我没有对该函数进行比较。

Since you cannot use the long type with xrange() on Python 2, I did not include a comparison for that function.

这篇关于为什么Python 3比Python 2慢很多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆