在Python中计算经过时间时的困惑?

2 投票
2 回答
641 浏览
提问于 2025-04-16 02:30

我想比较一下Python 2.6和3.1的性能,所以我写了一个简单的程序 test.py,这个程序会执行一些基本的耗时操作:

from time import time
start = time()
q = 2 ** 1000000000
q += 3 << 1000000000
print(q.__sizeof__(), time() - start)

但是我得到了意想不到的结果。在分别运行命令 time python2.6 test.pytime python3.1 test.py 后,输出结果是这样的:

(133333364, 0.37349200248718262)

real    0m35.586s
user    0m28.130s
sys 0m2.110s

还有,

133333360 0.312520027161

real    0m26.413s
user    0m17.330s
sys 0m2.190s

我原本以为这两个版本的结果在比较 time 命令的输出和程序内部的运行时间时会很接近。那这是什么原因呢?

2 个回答

3

可能有很多原因,比如在 sys.path 上有不同的目录和压缩文件,初始化时自动加载或执行的代码,或者平台上运行的其他进程——你的代码并不是完全独立的,也不能重复运行,因此它的结果价值不大。要测量性能,使用 python -mtimeit 会好得多,真的好得多。

编辑: 一些数字...:

$ py26 -mtimeit 'q=2**1000000000; q+=3<<1000000000'
10 loops, best of 3: 466 msec per loop
$ py31 -mtimeit 'q=2**1000000000; q+=3<<1000000000'
10 loops, best of 3: 444 msec per loop

这些准确测量了 += 的时间(在3.1版本中稍微优化了一下,可以重复测量)。如果你想测量位移幂运算的时间,那当然不能使用字面量(因为字面量在编译时就计算好了,而不是在运行时:这也是为什么你希望所有重要的代码都放在模块的函数中,而不是放在顶层代码或主脚本中……这样编译器可以尽可能多地做一些工作,尽管它没有什么严肃的优化;-)。例如:

$ py31 -mtimeit -s't=2' 'q=t**1000000'
10 loops, best of 3: 19.4 msec per loop
$ py31 -mtimeit -s't=3' 'q=t<<1000000'
10000 loops, best of 3: 150 usec per loop

(用你正在使用的较大右侧操作数来做这些真的太慢了,我有点不耐烦;-)。混合这些操作在测量上当然会是个悲惨的灾难,因为相对较快的操作会在混合中基本消失!-) 幸运的是,没有什么好的理由去混合——毕竟,timeit 是为了基准测试而设计的!-)

2

嘿,这个问题挺有意思的,我花了一些时间才搞明白:

from time import time
start = time()
q = 2 ** 1000000000 # number literal
q += 3 << 1000000000 # still a literal
print(q.__sizeof__(), time() - start)

Python的编译器会先计算出q的值。当脚本运行时,解释器会记录时间,加载已经计算好的值,然后再记录一次时间。结果不出所料,这两次的时间差不多。

time则是测量整个过程(编译加运行)花了多长时间。

撰写回答