Python timeit偶尔返回负值,timeit中可能存在错误

Python timeit偶尔返回负值,timeit中可能存在错误,python,time,Python,Time,我已经解决了一些问题,并决定添加计时,因此通过以下代码段将timeit添加到timemain()(为了方便起见,将全局RESULT存储在main()中) 很好。但是,有些人跑得太快了,我以为我能做到 t = timeit.timeit(main, 'gc.enable()', number=1) if (t < 0.001): t2 = timeit.timeit(main, 'gc.enable()', number=1000) 现在,如果我将重复计数更改为100000或更多,

我已经解决了一些问题,并决定添加计时,因此通过以下代码段将
timeit
添加到time
main()
(为了方便起见,将全局
RESULT
存储在
main()
中)

很好。但是,有些人跑得太快了,我以为我能做到

t = timeit.timeit(main, 'gc.enable()', number=1)
if (t < 0.001):
    t2 = timeit.timeit(main, 'gc.enable()', number=1000)
现在,如果我将重复计数更改为100000或更多,我根本看不到负t2值,每次呼叫的时间始终在2.4e-5秒左右

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

repeats timing  2.4194581894745244e-05 sec per call
repeats timing  1.8200670315524775e-05 sec per call
repeats timing  2.4408832248987168e-05 sec per call
repeats timing  2.4378118077314547e-05 sec per call
repeats timing  1.8361976570139902e-05 sec per call
repeats timing  1.8055080028738498e-05 sec per call
repeats timing  1.8102133534236732e-05 sec per call
repeats timing  2.4485323058654477e-05 sec per call
repeats timing  3.118363087991698e-05 sec per call
repeats timing  1.803846408685413e-05 sec per call
最后,将重复计数设置为1000,并删除初始(repeat=1)timeit。同样的结果,一些负面和大量反弹

我使用Python2.7重复了这个设置,结果类似——其他所有的都是3.4版

对我来说,当总时间与系统计时器中断的顺序相同时,这看起来像是timeit功能中的一个bug,但我认为可能我遗漏了什么

增加

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

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

增加


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

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

Microsoft对MSDN上的问题有详细的描述:


AMD为Windows XP系统上的此问题发布了一个修复程序,名为。

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

Microsoft对MSDN上的问题有详细的描述:


AMD针对Windows XP系统上的此问题发布了一个名为的修复程序。

您是否正在运行Windows?在旧处理器上?是的,我的笔记本电脑被偷得很厉害,所以我现在使用的是旧的Windows XP SP3和Athlon 64 X2双核3800+。很简单:收集上面显示的负时间间隔,直到你有足够的时间在笔记本电脑被偷之前返回并防止被盗。我喜欢你回答msw,但仍然想知道timeit是否可以可靠地使用。这个函数的文档似乎暗示了精确的计时,但我怀疑这是基于一个片段的多次重复。不过,如果没有时间旅行或错误代码,负值似乎不太可能出现。您正在运行Windows吗?在旧处理器上?是的,我的笔记本电脑被偷得很厉害,所以我现在使用的是旧的Windows XP SP3和Athlon 64 X2双核3800+。很简单:收集上面显示的负时间间隔,直到你有足够的时间在笔记本电脑被偷之前返回并防止被盗。我喜欢你回答msw,但仍然想知道timeit是否可以可靠地使用。这个函数的文档似乎暗示了精确的计时,但我怀疑这是基于一个片段的多次重复。不过,如果没有时间旅行或错误代码,负值似乎不太可能出现。
# 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
repeats timing  2.4194581894745244e-05 sec per call
repeats timing  1.8200670315524775e-05 sec per call
repeats timing  2.4408832248987168e-05 sec per call
repeats timing  2.4378118077314547e-05 sec per call
repeats timing  1.8361976570139902e-05 sec per call
repeats timing  1.8055080028738498e-05 sec per call
repeats timing  1.8102133534236732e-05 sec per call
repeats timing  2.4485323058654477e-05 sec per call
repeats timing  3.118363087991698e-05 sec per call
repeats timing  1.803846408685413e-05 sec per call