timeit偶尔会返回一个负值,可能是timeit中的错误

时间:2014-07-26 22:39:45

标签: python time

我处理了Project Euler个问题并决定添加时间,因此通过以下代码段将timeit添加到时间main()(在{{1}中存储全局RESULT为方便起见)

main()

工作正常。但是,有些人跑得这么快我以为我能做到这一点。

t = timeit.timeit(main, 'gc.enable()', number=1)
print("# Euler", PROBLEM, ".py RESULT: ", RESULT))

它有时会起作用。但是如果我反复运行这个,我有时会得到t2的负值。以Euler#2为例,我连续5次运行这些结果。

t = timeit.timeit(main, 'gc.enable()', number=1)
if (t < 0.001):
    t2 = timeit.timeit(main, 'gc.enable()', number=1000)

现在,如果我将重复次数更改为100,000或更多,我根本看不到负t2值,每次通话的时间一直在每次通话2.4e-5秒左右。

如果我重复10,000次,我会看到新的行为。 t2始终为正,但价值反弹很多。我跑了10次

# Euler2.py RESULT: 4613732  3.17869758716347e-05 seconds
repeats timing  -3.7966224778973e-05 sec per call

# Euler2.py RESULT: 4613732  3.1558464885145785e-05 seconds
repeats timing  2.4836235955056177e-05 sec per call

# Euler2.py RESULT: 4613732  3.131149340411519e-05 seconds
repeats timing  -3.5684903805855466e-05 sec per call

# Euler2.py RESULT: 4613732  3.177450256451194e-05 seconds
repeats timing  2.4558941864410162e-05 sec per call

# Euler2.py RESULT: 4613732  3.158939868681022e-05 seconds
repeats timing  2.4268726425449536e-05 sec per call

最后,将重复计数设置为1000并删除初始(重复= 1)时间。同一时间的结果,一些负面因素和大量反弹。

我使用Python 2.7重复了这个集合,类似的结果 - 其他一切都是版本3.4

对我来说,当总时间与系统计时器中断的顺序相同时,这看起来像timeit功能中的一个错误,但我想也许我错过了一些东西。

ADDED

我还应该补充一点,我知道其他计时器功能,包括perf_counter()。

我特别询问timeit(),因为我认为它是一个易于使用的hi-hres计时器,我可以在新旧版本的python中使用,并且如果它可以被信任,我希望继续这样做。

ADDED

根据提供的答案,我在pef_counter()上更改了我的时序代码,果然,我有时也得到负值。因此,如果您在旧窗口框中使用,则小的计时增量根本不可靠。这就是我想知道的。让我觉得它在Python堆栈中的原因是,对于非常小的时间,值似乎是准确的。应该猜到它是Windows和设备驱动程序的组合。

1 个答案:

答案 0 :(得分:4)

在Windows上,timeit默认使用time.clock作为时间源,而后者又使用Windows API QueryPerformanceCounter。根据Windows的版本和机器的功能QueryPerformanceCounter使用处理器的时间戳计数器(TSC)作为计时器。许多较旧的多处理器机器无法使TSC在处理器之间保持同步,并且没有正确地向Windows报告,或者有错误尝试这样做。这导致QueryPerformanceCounter返回结果,当进程在不同的处理器上执行时,它们似乎会跳转。

Microsoft在MSDN上详细描述了该问题:http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx

AMD在Windows XP系统上发布了一个名为AMD Dual Core Optimizer的解决方案。