Python time.sleep 与忙等待的准确性

Posted

技术标签:

【中文标题】Python time.sleep 与忙等待的准确性【英文标题】:Python time.sleep vs busy wait accuracy 【发布时间】:2013-07-04 04:52:57 【问题描述】:

我正在使用 python 标准库中的 time.sleep 函数,发现它不足以应对亚毫秒级的延迟。通过测试,我发现它实际上等待 1.1-1.2 毫秒等待 1 毫秒。实施繁忙的等待使准确度在 1% 以内。我用过:

def busy_wait(dt):   
    current_time = time.time()
    while (time.time() < current_time+dt):
        pass

并且可以在 0.0001 秒内达到 1% 的准确率。

我的主要问题是:

为什么睡眠功能如此不准确(可能是 C 问题)?获得具有更高时钟速度的更好 CPU 会改变这种情况吗? 为什么有人会使用睡眠?我看到的唯一优势(节能)仅限于嵌入式系统,不是吗? 是否可以通过校准来补偿睡眠的不准确性?像这样: 定义睡眠(dt): 睡眠(校准功能(dt))

顺便说一句,我读到睡眠在等待时间长的情况下甚至无法正常工作:Upper limit in Python time.sleep()? 我还在 SO 上的某处读到了制作更短时间间隔的循环以提高精度,但是当我想延迟 0.01 秒时这是没用的。 Karl Voigtland 提到使用 ctypes 的 nanosleep,但我觉得这太过分了,time.sleep 应该做它的预期行为。

time.sleep 是一个损坏的 python 功能?还是没有人足够关心精确的时间测量?

【问题讨论】:

How accurate is python's time.sleep()?的可能重复 是的,我认为这是一个操作系统调用,但现在我想知道为什么他们在忙碌等待时使用操作系统调用更好。 繁忙的等待会占用 CPU 时间并阻塞 CPU。睡眠会进行上下文切换并且不会阻止其他执行(它会“阻止”您的执行)。一般来说,如果你真的需要确切的时间,你只会忙着等待,即使那样,你仍然受限于操作系统对 CPU 的需求,这可能会让你离开…… 也可能是普遍感兴趣的问题"How can I get the Windows system time with millisecond resolution?"和文章"Windows Timer Resolution: Megawatts Wasted" @JDong:在一般情况下忙等待并不是更好,因为操作系统可以在任何时候抢占您的程序。因此,根据 CPU 负载和调度程序的反复无常,阳光下的任何睡眠策略都可能是任意糟糕的。 【参考方案1】:

在 Windows 上,操作系统睡眠功能(Python 必须使用)只能在当前计时器间隔的倍数上唤醒线程。通常,该范围在 1.0 ms 和 15.6 ms 之间。降低定时器间隔会很方便,因为它可以缩短睡眠时间,但会浪费电力,正如我在这篇文章中所写的那样:

http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

忙碌的等待可能会提供更好的准确性,但通常是一个可怕的想法,因为它会浪费更多的电力并从更值得的任务中窃取 CPU 时间:

https://randomascii.wordpress.com/2012/06/05/in-praise-of-idleness/

最后,忙等待的准确性取决于你使用什么定时器函数来获取当前时间,也可能取决于定时器间隔:

https://randomascii.wordpress.com/2013/05/09/timegettime-versus-gettickcount/

你为什么要睡这么短的时间?通常,最好等待某事发生——等待某个事件——而不是等待这么短的时间。

【讨论】:

事实上 Python time.sleep() 使用带有超时的 WaitForSingleObject() 调用来捕获等待期间的任何 Ctrl-C(通过发出事件信号的 SetConsoleCtrlHandler()。) 应用程序是一种宏;我有一组想要非常准确地模拟的动作。我已经学会了如何在 C 中做到这一点,但还没有在 Python 中找到规范的解决方案。我的问题有点无法回答,所以我现在接受你的回答。感谢您的洞察力。 @schlenk 感谢您提供有关 time.sleep() 实现的信息。关于超时何时到期的规则与 Sleep() 的规则基本相同(因为调度程序仅在发生某些事情或触发定时器中断时运行)所以答案仍然适用。【参考方案2】:

这是一个重复的问题,但无论如何我都会尽我所能在这里回答。

睡眠函数是一种操作系统调用,它与忙等待不同,它不会阻塞线程。如果你有一个多线程脚本,它不应该阻塞其他线程。 睡眠功能在 Windows 中不准确,因为它不是实时操作系统(不确定这意味着什么)。如果您严格要求等待的准确性,那么忙碌的等待是您的最佳选择。否则,time.sleep() 可能是首选。操作系统调用 sleep 不准确的原因可能是因为它依赖于操作系统在正确的时间返回,并且依赖于操作系统调度程序的精度。

【讨论】:

以上是关于Python time.sleep 与忙等待的准确性的主要内容,如果未能解决你的问题,请参考以下文章

Python - 准确的 time.sleep

更准确的 time.sleep 用于 Python 3 中的短(毫秒)延迟? [复制]

python函数深入浅出 16.time.sleep()函数详解

Python - time.sleep 的替代品

python 如何封装在某带参数函数之后等待时间?

Python 的 time.sleep()