为什么 c++11 sleep_for 微秒实际上睡眠毫秒?

nic*_*ang 5 c++ operating-system thread-sleep c++11

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

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

nic*_*ick 6

sleep_for文档中,您可以看到:

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

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

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


Ted*_*gmo 6

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

有没有什么简单的方法可以保证我睡眠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);
}
Run Code Online (Sandbox Code Playgroud)

演示

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

  • 注意:这是玩具代码。在任何情况下都不要实际使用这样的代码。它有几个严重的缺陷。例如,在超线程系统上,等待线程可能会导致共享物理核心的另一个线程挨饿,甚至会因核心间通信资源饱和而减慢系统的速度。当时间最终到期时,代码将把所有错误预测分支的母亲清除缓存。 (2认同)

eer*_*ika 5

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

[thread.req.timing]

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

名称以 _for 结尾的函数采用指定持续时间的参数。...给定持续时间参数 D t,超时的实时持续时间为 D t +D i +D m

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

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

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

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

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

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