2016-03-02 36 views
9

让我们下面的一段代码,简单地衡量std::this_thread::sleep_for调用20ms的持续时间: 的std :: this_thread :: sleep_for睡觉短于​​预期VS2015

#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的),我得到的结果不如预期,即:

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运行,结果多少有些令人吃惊和不尊重来自msdncppreference.com承诺说明(即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 

怎样的可能,以及如何可以让VS2015的sleep_for只要预期至少睡觉?

的问候,的Dawid

编辑:

按照要求那些是我的设置和操作系统的详细信息:
OS

  • Windows 7专业版64位

  • 视觉工作室:2010旗舰版,2013社区,2015年专业与更新1个

编译器设置

  • 为Win32控制台应用程序的默认设置,

  • 任何调试和发布配置,

  • 任何x86和x64目标平台archit ectures

+0

在早期唤醒的情况下,我通常在循环中使用'sleep_until()'。我认为早期唤醒不应该发生,但在GCC Linux上,至少,每当进程收到信号时(显然这里不是你的问题),提早醒来似乎就会发生。 – Galik

+0

我在本地看不到相同的结果或例如在http://rextester.com/l/cpp_online_compiler_visual(它也使用VS2015)。考虑添加更多有关您的确切编译器设置,目标架构,主机操作系统,机器规格等的信息。 – Yirkha

+0

@Yirkha:我在描述中添加了有关我的条件的更多详细信息。至于你的结果 - 它看起来像在我的系统中寻找一点点差异。 – dawid

回答

8

在VS2015的sleep_for()方法实现已经包含围绕Sleep()系统调用一个循环,所以任何虚假唤醒不会影响它 - 看到_Thrd_sleep()VC\crt\src\stl\cthread.c


你的问题的原因是最有可能的事实是sleep_for(),并sleep_until()它调用里面,使用chrono::system_clock计算时间等待,但要测量使用chrono::steady_clock时期。

这两个计时器可能具有相同的精度,但不一定相同的精度。那么可能发生system_clock滞后一点,而steady_clock已经提前几微秒,并且使用system_clock计算的等待实际上比请求的要短。


在这种情况下,准确,steady_clock使用QueryPerformanceCounter()(见VC\include\chrono,搜索struct steady_clock),所以这将是非常准确和精确的执行,因为这是首选的Windows API来使用精确的时间测量。

system_clock使用GetSystemTimePreciseAsFileTime()(见VC\include\chrono,搜索struct system_clock),并承诺“的精度的最高水平(< 1微秒)”也可以实现。唉,正如MSDN页面所说,这个API只支持Windows 8以上版本,并且您在Windows 7机器上只能以ms精度与旧的GetSystemTimeAsFileTime()卡住。这很可能是您测量错误的结果。


根据您的具体使用情况,您可能会以不同的方式处理这个问题。我会考虑忽略这个小错误,因为暂停线程并等待调度程序将其唤醒并不会非常准确。

+0

看起来事情的原因来自'sleep_for'使用的时钟和我的测量方法的差异。检查我是否已经暂时将测量时钟更改为'system_clock',并且结果与预期一致。然而,由于你没有在本地再现这种效果,所以我觉得你的'sleep_for'使用'steady_clock',这是相当可疑的。如果是这样,如果它依赖于操作系统的条件,有没有办法让'sleep_for'使用'steady_clock'? – dawid

+0

这是在CRT内部实现的,甚至不通过'chrono'界面,所以你将不得不重建它 - 所以不。 Windows升级> = 8会解决所有问题,或者您可以在受影响的平台上添加少量的持续时间(以使“等待> = X”的要求始终为真)。 – Yirkha

2

虽然标准说实现应该使用的*_for计时功能的steady_clock,这不是必需的。如果使用非稳态时钟,则时钟调整可能导致睡眠时间缩短。在这种情况下,定时功能可能不会提供如标准所述的有用功能

但是,您的结果显示持续下降,我认为这可能表明行为不符合标准。

您可以通过使用自己选择的时钟自己测量时间并在循环中休眠,直到目标时间过去,从而解决此类问题。

相关问题