daw*_*wid 9 c++ c++11 visual-studio-2013 visual-studio-2015
让我们得到以下代码,它只是测量std::this_thread::sleep_for20ms调用的持续时间:
#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";
}
}
Run Code Online (Sandbox Code Playgroud)
当使用工具集v120(VS2013)编译运行时,我得到了预期的结果,即:
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
Run Code Online (Sandbox Code Playgroud)
但是当使用VS2015的工具集v140运行时,结果有点令人惊讶,并且不遵守msdn和cppreference.com sleep_for描述的承诺(sleep_for阻止至少指定的当前线程的执行sleep_duration).它们如下:
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
Run Code Online (Sandbox Code Playgroud)
它是如何可能的,我怎样才能使VS2015 sleep_for至少在预期的时间内进入睡眠状态?
此致,Dawid
编辑:
根据要求,这些是我的设置和操作系统详细信息:
OS:
Windows 7专业版64位
Visual Studios:2010年终极版,2013年社区版,2015年专业版,更新版1
编译器设置:
Win32控制台应用程序的默认设置,
任何调试和发布配置,
任何x86和x64目标平台体系结构
该sleep_for()在VS2015方法实现已经包含周围的循环Sleep()的系统调用,因此任何虚假唤醒不会影响它-看到_Thrd_sleep()的VC\crt\src\stl\cthread.c.
您的问题的原因很可能是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)实现,它承诺"尽可能高的精度(<1us)".唉,正如MSDN页面所说的那样,这个API只能从Windows 8开始支持,并且GetSystemTimeAsFileTime()在Windows 7计算机上只需要ms精度就可以使用旧版本.这很可能是您的测量误差的结果.
根据您的具体用例,您可能会以不同的方式处理此问题.我认为只是忽略小错误,因为暂停线程并等待调度程序将其唤醒将无论如何都不会非常准确.