【问题标题】:why c++11 sleep_for microseconds actually sleep for millisecond?为什么 c++11 sleep_for microseconds 实际上睡了毫秒?
【发布时间】:2020-03-08 06:07:48
【问题描述】:

我在我的 centos 7 服务器中调用了这个函数。

我发现 std::this_thread::sleep_for(chrono::nanoseconds(1)) 实际上睡了一毫秒,有什么解释吗?我认为这可能是由操作系统设置引起的?

【问题讨论】:

  • 您是否使用时钟来测量睡眠时间?你的时钟精度可能是 1 毫秒吗?
  • @nick 我做了一个快速循环工作,比如 {for (i=0;i
  • 很可能你的时钟分辨率不超过 1 ns。
  • sleep_for 的规范是它在至少指定的持续时间内阻止当前线程的执行。实际上,由于调度延迟(任何操作系统中的调度程序都有一定的粒度)和资源争用,它会比这更长。此外,唯一允许精确控制时间的操作系统(例如,将强制睡眠持续时间的上限和下限,而不仅仅是下限)是硬实时系统。大多数通用 unix 操作系统都不是硬实时的。

标签: c++ c++11 operating-system thread-sleep


【解决方案1】:

其他答案涵盖了您提出的问题,但您还在 cmets 中提出了一个问题:

有什么简单的方法可以保证我睡1us?

不用调用sleep_for,产生线程的执行槽,你可以忙着睡觉。也就是说,循环直到经过一定的时间。它通常会以使 CPU 线程无法用于执行其他任何操作为代价来获得更准确的结果。

这是一个名为busy_sleep() 的函数示例:

// get a rough estimate of how much overhead there is in calling buzy_sleep()
std::chrono::nanoseconds calc_overhead() {
    using namespace std::chrono;
    constexpr size_t tests = 1001;
    constexpr auto timer = 200us;

    auto init = [&timer]() {
        auto end = steady_clock::now() + timer;
        while(steady_clock::now() < end);
    };

    time_point<steady_clock> start;
    nanoseconds dur[tests];

    for(auto& d : dur) {
        start = steady_clock::now();
        init();
        d = steady_clock::now() - start - timer;
    }
    std::sort(std::begin(dur), std::end(dur));
    // get the median value or something a little less as in this example:
    return dur[tests / 3];
}

// initialize the overhead constant that will be used in busy_sleep()
static const std::chrono::nanoseconds overhead = calc_overhead();

inline void busy_sleep(std::chrono::nanoseconds t) {
    auto end = std::chrono::steady_clock::now() + t - overhead;
    while(std::chrono::steady_clock::now() < end);
}

Demo

注意:这是在被接受后更新的,因为我注意到开销计算有时可能会出错。更新后的示例应该不那么脆弱。

【讨论】:

    【解决方案2】:

    sleep_for 文档中,您可以看到:

    至少指定的 sleep_duration 内阻止当前线程的执行。

    由于调度或资源争用延迟,此函数可能比 sleep_duration 阻塞更长的时间

    最可能的原因是您的进程调度程序将睡眠线程踢出并且没有重新调度它一毫秒。

    【讨论】:

    • 谢谢nick,请问有什么简单的方法可以保证我睡1us吗?
    【解决方案3】:

    让我们首先检查一下规范为您提供了什么保证(引自最新的 C++ 标准):

    [thread.req.timing]

    实现在从超时返回时必然会有一些延迟。 中断响应、函数返回和调度中的任何开销都会导致“实现质量”延迟,表示为持续时间 Di。 理想情况下,此延迟为零。 此外,任何对处理器和内存资源的争用都会导致“管理质量”延迟,表示为持续时间 Dm。 延迟持续时间可能因超时而异,但在所有情况下,越短越好。

    名称以 _for 结尾的函数采用指定持续时间的参数。 ... 给定一个持续时间参数 Dt,超时的实时持续时间是 Dt+Di+D.

    实现提供的时间分辨率取决于操作系统和硬件。 ...

    因此,预计睡眠时间比作为参数给出的 Dt 长。

    假设您的测试是正确的,我们可以使用它来计算 Di+Dm 在您的系统上大约是一毫秒,而您的硬件在该特定执行中。

    有什么简单的方法可以保证我睡1us?

    不,不是所有系统上的标准 C++。

    这可能在具有实时功能的系统上成为可能。请参阅您所针对的系统的文档。

    【讨论】:

      猜你喜欢
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 2020-10-15
      • 2015-01-25
      • 1970-01-01
      • 2013-06-02
      • 2020-11-21
      相关资源
      最近更新 更多