【问题标题】:Precision time sleep using chrono使用chrono精确时间睡眠
【发布时间】:2015-02-04 00:10:54
【问题描述】:

我希望我的应用程序正好休眠 2000 微秒:

#include <iostream>
#include <chrono>
#include <thread>

std::cout << "Hello waiter" << std::endl;
std::chrono::microseconds dura( 2000 );

auto start = std::chrono::system_clock::now();
std::this_thread::sleep_for( dura );
auto end = std::chrono::system_clock::now();

auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Waited for " << elapsed.count() << " microseconds" << std::endl;

这会导致

Waited for 2620 microseconds

这种差异从何而来?有没有更好(更精确)的方法可用?

谢谢!

【问题讨论】:

  • 操作系统对于何时应该安排线程有自己的看法,并且您只能保证获得至少 dura ms 的睡眠时间。
  • dlf 是对的,操作系统的细节很有趣。在虚拟机中运行测试也会产生影响。
  • 忙等待可能会以处理器资源为代价提供更好的精度。这是一笔交易。
  • 我使用的是 MacOS 10.10

标签: c++ chrono


【解决方案1】:

引自 cppreference(见sleep_for):

由于调度或资源争用延迟,此函数可能会阻塞超过 sleep_duration。

我认为这是最可能的解释。具体细节取决于您的环境,尤其是您的操作系统。

总的来说,我认为没有可移植的方法来避免它(不可移植的选项包括增加线程优先级或降低 nice 级别)。

另一个,但不太可能,时差的原因是外部时钟调整(例如,由 ntp 守护程序引起)。使用steady_clock 是防止时钟调整的便携式保险。

【讨论】:

  • 使用steady_clock 代替system_clock 并没有什么不同。我也试过high_resolution_clock,结果一样。
  • @user2926577 是的,因为时钟调整很少发生(如果有的话),我认为我们可以在您的情况下排除这种情况。 high_resolution_clock 提高了滴答粒度。在您的消息中,它关闭了 600 多毫秒,这比我对std:::chrono::system_clock::period 的预期要多得多。看起来仍然像操作系统依赖问题。
【解决方案2】:

显然,sleep_for 一点也不精确。这个问题的工作解决方案是进入一个while循环,直到达到所需的持续时间。这使应用程序“休眠”了 2000 微秒。

bool sleep = true;
while(sleep)
{
    auto now = std::chrono::system_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - start);
    if ( elapsed.count() > 2000 )
        sleep = false;
}

【讨论】:

  • 这个解决方案不是异步的(又名 cpu-expensive)
  • @fiorentinoing 那么解决方案是 cpu 昂贵的吗?您的评论难以理解。
  • 不是基于事件的解决方案,而是基于蛮力计算和检查的解决方案,它是 cpu 昂贵的。这意味着等待 sleep 变为 false,CPU 可以轻松达到 100% 的使用率。
  • 不仅浪费cpu时间,而且也不能保证在循环过程中进程不会脱离上下文。
  • '这使应用程序“休眠”'我用胖托尼的声音读到。
猜你喜欢
  • 2021-12-19
  • 2012-07-24
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
相关资源
最近更新 更多