热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python2和python3之间的执行时间略有不同

最后,我在python中编写了一个简单的排列生成器(Knuth在“TheArt…4”中描述的“普通变化”算法的实现).我很好奇python2和python3之间的执行时间差异.这是

最后,我在python中编写了一个简单的排列生成器(Knuth在“The Art … 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?

提前谢谢您的回答:)

解决方法:

这实际上是一个非常有趣的问题.

我使用了以下在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:]如果我只是在循环开始时计算一个元组并为每个产量返回它声明,两个版本的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
>>>

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


推荐阅读
author-avatar
zmhua123_681
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有