【问题标题】:clock_gettime() returns about 1-2ms inaccuracy every 50-100ms (Debian wheezy on Virtualbox)clock_gettime() 每 50-100 毫秒返回大约 1-2 毫秒的误差(Virtualbox 上的 Debian wheezy)
【发布时间】:2014-08-18 09:49:34
【问题描述】:

不久前我有一个密切相关的线程here

但是,将cin.ignore() 替换为usleep(50e3)。它不会每 50 毫秒准确报告一次。时钟报告

Time Passed:    s: 0 ms: 50
Time Passed:    s: 0 ms: 101
Time Passed:    s: 0 ms: 152
Time Passed:    s: 0 ms: 202
Time Passed:    s: 0 ms: 252
Time Passed:    s: 0 ms: 303
Time Passed:    s: 0 ms: 353
Time Passed:    s: 0 ms: 403
Time Passed:    s: 0 ms: 454
Time Passed:    s: 0 ms: 504
Time Passed:    s: 0 ms: 554
Time Passed:    s: 0 ms: 605
Time Passed:    s: 0 ms: 657
Time Passed:    s: 0 ms: 708
Time Passed:    s: 0 ms: 758
Time Passed:    s: 0 ms: 808
Time Passed:    s: 0 ms: 862
Time Passed:    s: 0 ms: 915
Time Passed:    s: 0 ms: 965
Time Passed:    s: 1 ms: 15
Time Passed:    s: 1 ms: 66
Time Passed:    s: 1 ms: 116
Time Passed:    s: 1 ms: 169
Time Passed:    s: 1 ms: 221
Time Passed:    s: 1 ms: 271
Time Passed:    s: 1 ms: 322
Time Passed:    s: 1 ms: 372
Time Passed:    s: 1 ms: 423
Time Passed:    s: 1 ms: 473
Time Passed:    s: 1 ms: 524
Time Passed:    s: 1 ms: 574
Time Passed:    s: 1 ms: 625
Time Passed:    s: 1 ms: 676
Time Passed:    s: 1 ms: 727
Time Passed:    s: 1 ms: 778
Time Passed:    s: 1 ms: 833
Time Passed:    s: 1 ms: 883
Time Passed:    s: 1 ms: 935
Time Passed:    s: 1 ms: 986
Time Passed:    s: 2 ms: 37
Time Passed:    s: 2 ms: 91
Time Passed:    s: 2 ms: 142
Time Passed:    s: 2 ms: 192
Time Passed:    s: 2 ms: 243
Time Passed:    s: 2 ms: 294
Time Passed:    s: 2 ms: 346
Time Passed:    s: 2 ms: 396
Time Passed:    s: 2 ms: 450
Time Passed:    s: 2 ms: 501
Time Passed:    s: 2 ms: 552
Time Passed:    s: 2 ms: 602
Time Passed:    s: 2 ms: 652
Time Passed:    s: 2 ms: 703
Time Passed:    s: 2 ms: 753
Time Passed:    s: 2 ms: 804
Time Passed:    s: 2 ms: 855
Time Passed:    s: 2 ms: 906
Time Passed:    s: 2 ms: 956
Time Passed:    s: 3 ms: 7
Time Passed:    s: 3 ms: 57
Time Passed:    s: 3 ms: 107
Time Passed:    s: 3 ms: 158
Time Passed:    s: 3 ms: 208
Time Passed:    s: 3 ms: 258
Time Passed:    s: 3 ms: 315
Time Passed:    s: 3 ms: 365
Time Passed:    s: 3 ms: 416
Time Passed:    s: 3 ms: 466
Time Passed:    s: 3 ms: 517
Time Passed:    s: 3 ms: 567
Time Passed:    s: 3 ms: 618
Time Passed:    s: 3 ms: 668
Time Passed:    s: 3 ms: 719
Time Passed:    s: 3 ms: 769
Time Passed:    s: 3 ms: 824
Time Passed:    s: 3 ms: 875
Time Passed:    s: 3 ms: 926
Time Passed:    s: 3 ms: 976
Time Passed:    s: 4 ms: 27
Time Passed:    s: 4 ms: 79
Time Passed:    s: 4 ms: 129
Time Passed:    s: 4 ms: 182
Time Passed:    s: 4 ms: 233
Time Passed:    s: 4 ms: 283
Time Passed:    s: 4 ms: 334
Time Passed:    s: 4 ms: 384
Time Passed:    s: 4 ms: 436
Time Passed:    s: 4 ms: 486
Time Passed:    s: 4 ms: 537
Time Passed:    s: 4 ms: 587
Time Passed:    s: 4 ms: 638
Time Passed:    s: 4 ms: 688
Time Passed:    s: 4 ms: 739
Time Passed:    s: 4 ms: 789
Time Passed:    s: 4 ms: 844
Time Passed:    s: 4 ms: 895
Time Passed:    s: 4 ms: 946
Time Passed:    s: 4 ms: 997
Time Passed:    s: 5 ms: 47
Time Passed:    s: 5 ms: 101
Time Passed:    s: 5 ms: 151
Time Passed:    s: 5 ms: 202
Time Passed:    s: 5 ms: 252
Time Passed:    s: 5 ms: 303
Time Passed:    s: 5 ms: 354
Time Passed:    s: 5 ms: 404
Time Passed:    s: 5 ms: 455

如您所见(抱歉,输出可能很长,但以防万一),存在一致的不准确性。

为什么会这样,是什么影响它以及如何解决?

【问题讨论】:

  • 来自usleep 的手册页:“由于系统安排了其他活动,暂停时间可能比请求的长。”

标签: c++ c linux time clock


【解决方案1】:

当您的进程通过调用sleep 函数进入睡眠状态时,系统调度程序会推迟唤醒它,直到花费了请求的时间。之后,它可能会唤醒进程,或者可能需要更长的时间。

usleep()函数会导致调用线程挂起 从执行到实时微秒数 由参数 useconds 指定的时间已过或有信号 传递给调用线程,它的动作是调用一个 信号捕捉功能或终止进程。 暂停 由于其他时间安排,时间可能比要求的长 系统的活动。

许多操作系统不保证它们会在睡眠时间结束后立即唤醒进程。

【讨论】:

  • 所以报告是正确的,但是从睡眠中醒来需要更长的时间?
  • @RoundPotato:是的,clock_gettime() 还不错,sleep ing 机制是主要问题。
【解决方案2】:

这是由于睡眠的工作原理,即使在实时操作系统中也是如此。

基本上,当你问“睡 X 时间”时,你不会问“在 X 时间唤醒我”,而是“不要在 X 时间之前给我打电话”。这就是为什么依赖时间的编程如此困难的原因,也是为什么视频游戏编程使用帧而不是毫秒的原因。

如果您的系统没有超载并且没有运行太长时间,那么这种不准确性加起来不会造成麻烦,如果是这样,您将需要另一种方法来检查时间(也许是 Universal时间?但你会依赖网络)。

【讨论】:

    【解决方案3】:

    数字刻度具有固有的量化误差(就像在任何 DAC/ADC 中一样),这意味着对于持续时间为 1 毫秒的刻度,您的误差范围可以从“几乎 0”到“几乎 1 毫秒”。

    MSDN article on timing 有一个完美的图片说明:

    (是的,有时 MSDN 实际上有有用且有见地的文章)与此文本:

    “如果硬件生成器以恒定速率提供滴答声,则可以通过简单地计算这些滴答声来测量时间间隔。生成滴答声的速率称为频率,以赫兹 (Hz) 表示。频率称为周期或滴答间隔,并以适当的国际单位制 (SI) 时间单位(例如,秒、毫秒、微秒或纳秒)表示。 时间间隔 定时器的分辨率等于周期。分辨率决定了区分任何两个时间戳的能力,并为可以测量的最小时间间隔设置了下限。这有时称为刻度分辨率。 时间的数字测量引入了 ± 1 滴答的测量不确定性,因为数字计数器以离散的步长前进,而时间不断前进。这种不确定性称为量化误差。对于典型的时间间隔测量,这种影响通常可以忽略不计,因为量化误差远小于被测量的时间间隔。”

    【讨论】: