我处理了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和设备驱动程序的组合。
答案 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的解决方案。