我不明白为什么当指定的持续时间增加时,调用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更长?
答案 0 :(得分:10)
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的精度旋转。但是请注意:您会有异常值。