为什么std :: future :: wait_for不等待正确的持续时间?

时间:2019-04-18 14:40:40

标签: c++ c++11

我不明白为什么当指定的持续时间增加时,调用std::future::wait_for时,测量的持续时间与指定的持续时间之间的差异为什么会增加?

当我告诉std::future等待10ns并测量经过的时间时,我得到〜2000ns。现在,10ns的持续时间非常短,因此可能要等待很短的时间,而相关的函数调用会涉及过多的开销。但是,当我告诉std::future等待100000ns并测量经过的时间时,我得到〜150000ns。当分别等待10和100微秒时,可以看到类似的效果。

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

using namespace std::chrono;
using namespace std::chrono_literals;

void f() { std::this_thread::sleep_for(1s); }

int main() {
  steady_clock::time_point start, end;

  std::future<void> future = std::async(std::launch::async, f);

  start = steady_clock::now();
  future.wait_for(10ns);
  end = steady_clock::now();
  std::cout << "10 -> " << (end - start).count() << '\n';

  start = steady_clock::now();
  future.wait_for(100000ns);
  end = steady_clock::now();
  std::cout << "100000 -> " << (end - start).count() << '\n';

  return 0;
}

我在Ubuntu 18.04上使用g++ future_test.cpp -lpthread和g ++ 7.3.0编译上述代码。

我可以解释类似的东西

10 -> 2000
100000 -> 102000

但这不是我得到的。这是多次执行的代表性结果:

10 -> 2193
100000 -> 154723

为什么从指定的持续时间到100'000ns的测量持续时间比〜2'000ns更长?

4 个答案:

答案 0 :(得分:10)

引用documentation

  

std::future_status wait_for( const std::chrono::duration& timeout_duration );

     

此功能可能比timeout_duration更长的时间   调度或资源争用延迟。

答案 1 :(得分:7)

睡眠并等待只会保证在您询问时至少等待 。由于硬件和调度限制会带来不可预知的延迟,因此睡眠或等待可能持续多长时间没有固定的最大值。

对于周期性应用程序(例如计时器),如果您等到某个时间点然后将该时间点增加固定的数量,则可以获得稳定的睡眠(平均)。如果继续执行此操作,只要线程足够频繁地唤醒,您将在一段时间内平均获得目标延迟。

答案 2 :(得分:2)

4 GHz时钟是每勾0.25秒。 10 ns就是40滴答,或者40条指令给出或获得。

要求10 ns的延迟意味着一切都非常荒谬;计算当前时间所需的时间很容易会超过10 ns。

所以您在这里测量的是:

start = steady_clock::now();
future.wait_for(10ns);
end = steady_clock::now();
std::cout << "10 -> " << (end - start).count() << '\n';

计算当前时间,等待开销(检查是否准备就绪等)所需的时间。

在第二种情况下:

start = steady_clock::now();
future.wait_for(100000ns);
end = steady_clock::now();
std::cout << "100000 -> " << (end - start).count() << '\n';

差异约为50,000 ns。那是秒的1/20000。

在这里,我们可能正在执行一些操作,例如将CPU置于低功耗模式,甚至设置自旋锁。

您可能正在上下文切换,但我想可能不会;切换到另一个上下文然后再返回可能会花费太多的精力。

当CPU中存在争用时,交互式OS上的时间分片通常约为1/50秒,或20000000ns。

答案 3 :(得分:0)

您正在要求实时的东西,这完全取决于系统。 这是操作系统的工作。但是,即使您使用RTOS,抢占式RT或类似的东西,我也不确定C ++ stdlib能否获得这种准确性。

在您需要时,只要系统可以为您提供,最好使用依赖于操作系统的调用。

无论如何,我通常以1ms的精度旋转。但是请注意:您会有异常值。