让我们使用以下代码,它只是测量用{20}调用的std::this_thread::sleep_for
的持续时间:
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::chrono;
int main()
{
for (int i = 0; i < 20; i++)
{
auto start = steady_clock::now();
this_thread::sleep_for(milliseconds(20));
auto end = steady_clock::now();
duration<double, milli> elapsed = end - start;
cout << "Waited " << elapsed.count() << " ms\n";
}
}
当使用工具集v120(VS2013&#39; s)编译运行时,我得到了预期的结果,即:
Waited 20.0026 ms
Waited 20.0025 ms
Waited 20.0025 ms
Waited 20.0026 ms
Waited 20.0025 ms
Waited 20.0025 ms
Waited 20.0026 ms
Waited 20.0025 ms
Waited 20.0025 ms
Waited 20.0026 ms
但是当使用VS2015的工具集v140运行时,结果有点令人惊讶,并且不尊重msdn和cppreference.com sleep_for
描述的承诺({ {1}}阻止至少指定sleep_for
的当前线程的执行。它们如下:
sleep_duration
它是如何实现的,如何使VS2015的Waited 19.7793 ms
Waited 19.9415 ms
Waited 19.6056 ms
Waited 19.9687 ms
Waited 19.608 ms
Waited 19.589 ms
Waited 20.5435 ms
Waited 19.5669 ms
Waited 19.6802 ms
Waited 19.5381 ms
至少能够在预期的时间内睡觉?
问候,Dawid
修改
根据要求,这些是我的设置和操作系统详细信息:
的 OS :
Windows 7 Professional 64位
视觉工作室:2010年终极版,2013社区,2015年专业人士及更新1
编译器设置:
Win32控制台应用程序的默认设置,
任何调试和发布配置,
任何x86和x64目标平台架构
答案 0 :(得分:8)
VS2015中的sleep_for()
方法实现已包含围绕Sleep()
系统调用的循环,因此任何虚假唤醒都不会影响它 - 请参阅_Thrd_sleep()
中的VC\crt\src\stl\cthread.c
。< / p>
问题的原因很可能是sleep_for()
和sleep_until()
内部调用的事实,正在使用chrono::system_clock
计算等待时间,但您正在衡量这段时间使用chrono::steady_clock
。
两个计时器可能具有相同的精度,但不一定具有相同的精度。然后可能会发生system_clock
滞后一点,而steady_clock
已经提前几μs,而使用system_clock
计算的等待实际上比请求的短。
在这种情况下,steady_clock
是使用QueryPerformanceCounter()
实现的(请参阅VC\include\chrono
,搜索struct steady_clock
),因此它会非常准确和精确,因为它是用于精确时间测量的首选Windows API。
system_clock
是使用GetSystemTimePreciseAsFileTime()
实现的(请参阅VC\include\chrono
,搜索struct system_clock
),这承诺“尽可能高的精度(&lt; 1us) “也。唉,正如MSDN页面所说,这个API仅支持从Windows 8启动,而您在Windows 7计算机上只需要ms精度就可以使用较旧的GetSystemTimeAsFileTime()
。这很可能是您的测量误差的结果。
根据您的确切用例,您可能会以不同的方式处理此问题。我认为只是忽略了小错误,因为暂停线程并等待调度程序将其唤醒将无论如何都不会非常准确。
答案 1 :(得分:2)
虽然标准说实现 应该steady_clock
使用*_for
计时功能,但这不是必需的。如果使用非稳定时钟,则时钟调整可能导致睡眠时间不足。在这种情况下,时序函数可能无法提供标准所指出的有用功能。
但是,您的结果显示出一致的短暂下降,我认为这可能表明行为不符合标准。
您可以通过自己使用自己选择的时钟测量时间并在循环中睡觉直到目标时间过去来解决此类行为。