【问题标题】:Wait accurate for 20 millisec等待准确 20 毫秒
【发布时间】:2016-04-14 12:45:36
【问题描述】:

我需要在某些事件之后在20 毫秒(用于发送 RTP 数据包)内执行一些准确的功能。我尝试了下一个变体:

std::this_thread::sleep_for(std::chrono::milliseconds(20));
boost::this_thread::sleep_for(std::chrono::milliseconds(20));
Sleep(20);

还有不同的变态:

auto a= GetTickCount();
while ((GetTickCount() - a) < 20) continue;

还尝试了微秒和纳秒。
所有这些方法在-6ms+12ms 的范围内都有错误,但它是不可接受的。如何使其正常工作?

我的意见,+-1ms 是可以接受的,但不能再多了。

UPDATE1:测量时间我使用std::chrono::high_resolution_clock::now();

【问题讨论】:

  • 您是否使用线程和计时器来执行此操作?
  • 您确定测量等待时间的计时器准确吗?
  • 也许this answer 对 SO 有帮助。
  • @ChrisF 现在我在一个(主)线程的空项目中对其进行测试。
  • @MikeCAT 我发现 GetTickCount() 不准确。但首先我使用了 std::chrono::high_resolution_clock::now();

标签: c++ windows time


【解决方案1】:

简而言之,由于操作系统内核管理时间和线程的方式,使用该方法不会获得更好的准确性。此外,您不能单独依靠静态间隔睡眠,否则您的流将很快偏离您预期的发送时钟速率,因为线程可能会被中断,或者它可能会在您的睡眠时间之后再次安排......因此您应该检查系统时钟以了解每次迭代要休眠多少时间(即介于 0 毫秒和 20 毫秒之间)。无需过多介绍,这也是为什么 RTP 流中有一个抖动缓冲区的原因......以解决数据包接收的变化(由于网络抖动或发送抖动)。因此,您可能无论如何都不需要 +/-1ms 级别的精度。

【讨论】:

    【解决方案2】:

    使用std::chrono::steady_clock,我在 Windows 7 上获得了大约 0.1 毫秒的精度。

    也就是说,简单地说:

    auto a = std::chrono::steady_clock::now();
    while ((std::chrono::steady_clock::now() - a) < WAIT_TIME) continue;
    

    这应该给你准确的“等待”(我说过大约 0.1 毫秒),至少。我们都知道这种等待是“丑陋的”并且应该避免,但它仍然是一种技巧,可能仍然可以很好地解决问题。

    您可以使用high_resolution_clock,这可能会为一些系统提供更好的准确性,但不能保证操作系统不会对其进行调整,而且您不希望这样。 steady_clock 应该保证不被调整,并且经常和high_resolution_clock 一样准确。

    至于“sleep()”函数非常准确,我不知道。也许其他人对此了解更多。

    【讨论】:

    • 您使用的是this_thread::sleep_for(std::chrono::milliseconds(n)); 还是别的什么?
    • 不,我不是用它来睡觉,而是用来测量某些代码的执行速度。关键是如果您使用它,您将获得所需的准确性。当谈到准确性“睡眠”时,我不知道,但它们可以避免,对吧?您的第二个版本将为您提供所需的准确性。
    【解决方案3】:

    在 C 中,我们在 time.h 中有一个 nanosleep 函数。

    nanosleep() 函数会导致当前线程暂停执行,直到 rqtp 参数指定的时间间隔已经过去,或者信号被传递到调用线程并且其操作是调用信号捕获函数或终止进程。

    下面这个程序会休眠 20 毫秒。

    int main()
    {
       struct timespec tim, tim2;
       tim.tv_sec = 0;
       tim.tv_nsec =20000000;//20 milliseconds converted to nano seconds
    
       if(nanosleep(&tim , NULL) < 0 )   
       {
          printf("Nano sleep system call failed \n");
          return -1;
       }
    
       printf("Nano sleep successfull \n");
     return 0;
    }
    

    【讨论】:

    • 这是用于什么平台的?
    • 虽然此代码可以回答问题,但提供有关它为什么和/或如何回答问题的额外上下文将显着提高其长期价值。请edit你的答案添加一些解释。
    猜你喜欢
    • 2015-09-13
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多