【问题标题】:Slightly different execution times between python2 and python3python2和python3之间的执行时间略有不同
【发布时间】:2011-06-01 06:52:21
【问题描述】:

最后,我在 python 中编写了一个简单的排列生成器(实现了 Knuth 在“艺术... 4”中描述的“普通更改”算法)。 我很好奇python2和python3在执行时间上的差异。 这是我的功能:

def perms(s):
    s = tuple(s)
    N = len(s)
    if N <= 1:
        yield s[:]
        raise StopIteration()
    for x in perms(s[1:]):
        for i in range(0,N):
        yield x[:i] + (s[0],) + x[i:]

在 python3 版本中,我只是将 print x 更改为 print(x),因为 print 是 py3 中的一个函数。 我都使用 timeit 模块进行了测试。

我的测试:

$ echo "python2.6:" && ./testing.py && echo "python3:" && ./testing3.py

python2.6:

args time[ms]
1 0.003811
2 0.008268
3 0.015907
4 0.042646
5 0.166755
6 0.908796
7 6.117996
8 48.346996
9 433.928967
10 4379.904032

python3:

args time[ms]
1   0.00246778964996
2   0.00656183719635
3   0.01419159912
4   0.0406293644678
5   0.165960511097
6   0.923101452814
7   6.24257639835
8   53.0099868774
9   454.540967941
10  4585.83498001

如您所见,对于少于 6 个参数的数量,python 3 更快,但随后角色颠倒,python2.6 表现更好。 由于我是python编程的新手,我想知道为什么会这样?或者也许我的脚本更适合 python2?

提前感谢您的友好回答:)

【问题讨论】:

  • 请使用正确的格式。
  • 首先,使用{} 按钮格式化您的代码。然后解释为什么这很重要。
  • `我只是想知道python2和python3之间的区别是什么导致了这个`。 Python3 与 python 2 有很大不同。它们甚至不向后兼容。您到底在寻找什么可以回答您的问题。您想获得每个版本的 C 代码吗?
  • "几乎相同的脚本,只是移植到 python3" 您是否对脚本进行了更改?如果是这样,您究竟做了哪些改变?请用您所做的确切更改更新问题。
  • @marcog:“假设”......总是一个错误。而“微不足道”的变化可以解释微不足道的时间差异。

标签: python testing time python-3.x execution


【解决方案1】:

这其实是一个很有趣的问题。

我使用了以下在 Python 2.6、2.7、3.0、3.1 和 3.2 上运行的脚本。

from __future__ import print_function
from timeit import Timer
from math import factorial

try:
    range = xrange
except:
    pass

def perms(s):
    s = tuple(s)
    N = len(s)
    if N <= 1:
        yield s[:]
        raise StopIteration()
    for x in perms(s[1:]):
        for i in range(0,N):
            yield x[:i] + (s[0],) + x[i:]

def testcase(s):
    for x in perms(s):
        pass

def test():
    for i in range(1,11):
        s = "".join(["%d" % x for x in range(i)])
        s = "testcase(\"%s\")" % s
        t = Timer(s,"from __main__ import testcase")
        factor = 100000
        factor = int(factor/factorial(i))
        factor = (factor>0) and factor or 1
        yield (i,(1000*min(t.repeat(5,factor))/factor))

if __name__=="__main__":
    print("args\ttime[ms]")
    for x in test():
        print("%i\t%f" % x)

平台是 Ubuntu 10.10,64 位,所有版本的 Python 都是从源代码编译的。我得到以下结果:

case@quad:~$ py27 perms.py
args    time[ms]
1   0.002221
2   0.005072
3   0.010352
4   0.027648
5   0.111339
6   0.618658
7   4.207046
8   33.213019
9   294.044971
10  2976.780891

case@quad:~$ py32 perms.py
args    time[ms]
1   0.001725
2   0.004997
3   0.011208
4   0.032815
5   0.139474
6   0.761153
7   5.068729
8   39.760470
9   356.358051
10  3566.874027

经过更多实验,我跟踪了片段的性能差异:x[:i] + (s[0],) + x[i:] 如果我只在循环开始时计算一个元组并为每个 yield 语句返回它,那么两个版本的 Python 运行速度相同. (而且排列是错误的,但这不是重点。)

如果我自己对该片段进行计时,它会明显变慢。

case@quad:~$ py27 -m timeit -s "s=(1,2,3,4,5);x=(1,2,3,4,5,6,7,8)" "x[:3] + (s[0],) + x[3:]"
1000000 loops, best of 3: 0.549 usec per loop
case@quad:~$ py32 -m timeit -s "s=(1,2,3,4,5);x=(1,2,3,4,5,6,7,8)" "x[:3] + (s[0],) + x[3:]"
1000000 loops, best of 3: 0.687 usec per loop

接下来我使用 dis.dis() 来查看两个版本生成的字节码。

case@quad:~/src/Python-3.0.1$ py32
Python 3.2b2 (r32b2:87398, Dec 21 2010, 21:39:59) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> s=(1,2,3,4,5)
>>> x=(1,2,3,4,5,6,7,8)
>>> def f(s,x):
...   return x[:3] + (s[0],) + x[3:]
... 
>>> dis.dis(f)
  2           0 LOAD_FAST                1 (x) 
              3 LOAD_CONST               0 (None) 
              6 LOAD_CONST               1 (3) 
              9 BUILD_SLICE              2 
             12 BINARY_SUBSCR        
             13 LOAD_FAST                0 (s) 
             16 LOAD_CONST               2 (0) 
             19 BINARY_SUBSCR        
             20 BUILD_TUPLE              1 
             23 BINARY_ADD           
             24 LOAD_FAST                1 (x) 
             27 LOAD_CONST               1 (3) 
             30 LOAD_CONST               0 (None) 
             33 BUILD_SLICE              2 
             36 BINARY_SUBSCR        
             37 BINARY_ADD           
             38 RETURN_VALUE         
>>> exit()
case@quad:~/src/Python-3.0.1$ py26
Python 2.6.6 (r266:84292, Oct 24 2010, 15:27:46) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> s=(1,2,3,4,5)
>>> x=(1,2,3,4,5,6,7,8)
>>> def f(s,x):
...   return x[:3] + (s[0],) + x[3:]
... 
>>> dis.dis(f)
  2           0 LOAD_FAST                1 (x)
              3 LOAD_CONST               1 (3)
              6 SLICE+2             
              7 LOAD_FAST                0 (s)
             10 LOAD_CONST               2 (0)
             13 BINARY_SUBSCR       
             14 BUILD_TUPLE              1
             17 BINARY_ADD          
             18 LOAD_FAST                1 (x)
             21 LOAD_CONST               1 (3)
             24 SLICE+1             
             25 BINARY_ADD          
             26 RETURN_VALUE        
>>> 

两个版本生成的字节码有很大不同。不幸的是,我不知道为什么字节码不同,所以我真的没有回答这个问题。但是切片和构建元组的性能确实存在显着差异。

【讨论】:

  • 你为什么说这些排列是错误的?我看不出它们有什么问题。
  • @kosa:为了消除创建元组的运行时间,我创建了一个长度正确的元组,并为范围(0,N)的所有迭代返回相同的元组。该特定测试返回的实际排列不正确,但 Python 2 和 3 的运行时间相同。 perms() 运行时间的近三分之二是片段:x[:i] + (s[ 0],) + x[i:]。由于该片段在 Python 3 上慢了 25%,并且它占运行时间的 65%,因此总运行时间应该慢 17% 左右,这与测试大致匹配。
  • 啊,现在我明白了。嗯,这就是我希望的答案。谢谢!
【解决方案2】:

Quoting:

3.0 的最终结果 概括是 Python 3.0 运行 pystone 基准大约 10% 比 Python 2.5 慢。最有可能的 最大的原因是删除 小整数的特殊情况。 有改进的余地,但它 将在3.0发布后发生!

>>> 4585.83498001/4379.904032
1.0470172283468882

因此,您会看到大约 5% 的减速。引用的文字说预计会放缓 10%。所以我会接受这是一个合理的减速。

但是,正如 herehere 所见,它一直在改进。因此,如果您担心 5% 的减速,请尝试 3.1 或 3.2。

【讨论】:

  • @ΤZΩΤZΙΟΥ 我没这么说。这是 3.0 发行说明中的​​引述。并且改进确实发生在 3.0 版本之后:在我上一段中提到的 3.1 和 3.2 中。
  • 你是对的;我在一台具有非常低对比度 LCD 屏幕(阅读:旧)的笔记本电脑上看到了您的回复,因此报价背景没有应有的那么明显。
【解决方案3】:

我当然会认为这些数字在统计上是微不足道的。

有太多因素在起作用,这些变化无法真正发挥任何意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多