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

why c++11 sleep_for microseconds actually sleep for millisecond?

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

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

sleep_for 文档中,您可以看到:

Blocks the execution of the current thread for at least the specified sleep_duration.

This function may block for longer than sleep_duration due to scheduling or resource contention delays.

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

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

[thread.req.timing]

Implementations necessarily have some delay in returning from a timeout. Any overhead in interrupt response, function return, and scheduling induces a “quality of implementation” delay, expressed as duration Di. Ideally, this delay would be zero. Further, any contention for processor and memory resources induces a “quality of management” delay, expressed as duration Dm. The delay durations may vary from timeout to timeout, but in all cases shorter is better.

The functions whose names end in _­for take an argument that specifies a duration. ... Given a duration argument Dt, the real-time duration of the timeout is Dt+Di+Dm.

The resolution of timing provided by an implementation depends on both operating system and hardware. ...

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

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

Is there any simple method can ensure i sleep for 1us?

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

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

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

Is there any simple method can ensure i sleep for 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

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