Python在所有系统上的执行时间不一致

4 投票
2 回答
3186 浏览
提问于 2025-04-18 13:25

有件事让我在使用Python时非常困扰……我原本以为这只是Windows的问题,但我错了。我可以用完全相同的代码多次运行,但每次的执行时间却差别很大。比如说,看看下面这段测试代码:

import math
def fib(count):
    x = 0
    while x < count:
        a = int(((((1 + math.sqrt(5)) / 2) ** x) - (((1 - math.sqrt(5)) / 2) ** (x))) / math.sqrt(5))
        x+=1

if __name__ == '__main__':  
    import timeit

    t = timeit.Timer("fib(1250)", setup="from __main__ import fib",)
    #print t.timeit(10)
    count = 10000
    results = t.repeat(count, 1)
    min = 0xFFFF
    max = 0
    sum = 0
    for i in results:
        i = i*1000.0
        if i < min: min = i
        if i > max: max = i
        sum+=i

    print "Min {:.3f} | Max {:.3f} | Max/Min {:.3f} | Avg {:.3f}".format(min, max, max/min, sum/count)

这段代码基本上是生成前1250个斐波那契数,重复执行10,000次,然后用timeit来测量每次运行所花的时间。接着,我把这些时间汇总,找出最小值、最大值、平均值,以及最小值和最大值之间的差异(也就是波动幅度)。

这是结果:

Windows: Min 3.071 | Max 8.903 | Max/Min 2.899 | Avg 3.228
Mac OS:  Min 1.531 | Max 3.167 | Max/Min 2.068 | Avg 1.621
Ubuntu:  Min 1.242 | Max 10.090 | Max/Min 8.123 | Avg 1.349

从结果来看,Linux的执行速度最快,但波动也最大,差别很大。不过其他系统的执行时间也有很大的变化:Mac的波动是200%,Windows是290%,而Linux竟然达到810%!

难道执行时间真的差这么多吗?timeit的准确性不够吗?我是不是漏掉了什么?我现在在做很多动画生成的工作,需要尽可能一致的时间。

2 个回答

4

我做了一个图,跟@drV的很像(给他投票,他是第一个!)——不同的是,我把结果进行了排序,这样你就能看到趋势线。这里的提示是,尽管最高值很高,但平均值却很低,所以最后有一些异常值。

enter image description here

我使用了pylab,只需在底部添加这个:

from pylab import *
results.sort()
plot(range(len(results)),results)
show()
10

你在测量非常短的时间,所以即使是很小的事情发生,也会对结果产生很大影响。

我在我的电脑上(OS X,Core i7,Python 2.7)运行了你的测试脚本,并画出了这个results的图:

这里输入图片描述

你可以看到,大部分时间的计时结果都是非常一致的,但偶尔会出现算法耗时更长的情况(因为有其他事情在发生)。


我对你的计时方法做了一个小调整:

results=t.repeat(10, 1000)

现在我们是在计时1000次函数调用的运行时间。总的时间自然还是一样的(10000次调用):

这里输入图片描述

现在你可以看到性能变得更加可预测了。你之前那些不稳定的计时结果,可能是因为计时的方法问题,而不是执行任何操作的时间真的有差别。在真实的操作系统环境中,毫秒级的计时是很困难的。即使你的电脑“什么都不做”,它仍然在切换任务、处理后台工作等等。


我明白最初的目的是不是为了计算斐波那契数列。但如果是的话,选择合适的工具会有很大区别:

import numpy as np

def fib(count):
    x = np.arange(count)
    a = (((1 + np.sqrt(5))/2) ** x - ((1 - np.sqrt(5)) / 2) ** x) / np.sqrt(5)
    a = a.astype('int')

这会得到:

Min 0.120 | Max 0.471 | Max/Min 3.928 | Avg 0.125

十倍的速度提升。


关于这个回答中的图片,它们是用matplotlib绘制的。第一个图是这样做的:

import matplotlib.pyplot as plt

# create a figure
fig = plt.figure()
# create axes into the figure
ax = fig.add_subplot(111)
# plot the vector results with dots of size 2 (points) and semi-transparent blue color
ax.plot(results, '.', c=(0, 0, 1, .5), markersize=2)

查看matplotlib的文档。使用IPythonpylab是最简单的入门方法。

撰写回答