热门标签 | 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
>>>

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


推荐阅读
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
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社区 版权所有