的std :: sleep_for在Windows 10不可预知的行为

问题描述 投票:3回答:2

最近我发现,由于未知原因,std::this_thread::sleep_for可以睡超过预期的10倍。这不只是一个或几个偶然的延迟,但可以持续数分钟,影响也非常std::condition_variable::wait_for显着的效果。

这里是我的代码:

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

using namespace std;

int main(int argc, char const *argv[])
{
    unsigned t = 0;
    auto start = ::std::chrono::steady_clock::now();
    for(unsigned i = 0; i < 100; ++i) {
        ::std::this_thread::sleep_for(chrono::milliseconds(1));
        t ^= i; // prevent overeager optimization
    }
    auto stop = ::std::chrono::steady_clock::now();
    auto elapsed = ::std::chrono::duration_cast<::std::chrono::milliseconds>(stop - start);
    ::std::cout << elapsed.count() << "\n";
    ::std::cerr << t << "\n";

  return 0;
}

我与Visual Studio命令行工具编译的具体步骤如下:

cl /EHsc /std:c++17 /O2 sleep_for.cpp

当我执行它,结果是有时接近150,有时到1500执行之间,没有环境的变化。可能是什么这样的效果的原因是什么?

更新1.它看起来这是一个操作系统的问题。除了std::thread::sleep_forstd::condition_variable::wait_until,我也试过定时器基​​于uvw library,具有相同的结果。无论我做什么,我不能让一个线程睡眠时间少于15毫秒。这种效果是在系统启动之后很明显的,而且比它显得更加难得。

摘要。有些人建议:阅读文档!他们警告过你! std::this_thread::sleep_for可能不稳定!但在另一方面,根据该文件,并没有什么错的,如果它工作更稳定,一个只需要知道如何做到这一点。杰里米Friesner提出了一个解决方案,我已经测试它和它的工作,呈现出10倍更好的性能和良好的稳定性平均值。是否使用std::this_thread::sleep_for以及如何做到这一点,你deside。我肯定会建议不要使用它,如果你正在开发一个救生设备等,但在许多情况下,它可能是非常有用的。

一篇好文章,讨论提高稳定性和分辨率的价格:https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

c++
2个回答
3
投票

纵观documentation

阻塞当前线程的至少指定sleep_duration执行。此功能可以阻止超过因调度或资源争用延迟sleep_duration更长。


1
投票

这个答案是从杰里米Friesner的评论创建。他建议在timeBeginPeriod(1)的开始尝试main()。这工作了!我创建的程序的修改,它运行快10倍。下面是代码:

#include <thread>
#include <iostream>
#include <chrono>
#include <windows.h>

using namespace std;

int main(int argc, char const *argv[])
{
    timeBeginPeriod(1);
    unsigned t = 0;
    auto start = ::std::chrono::steady_clock::now();
    for(unsigned i = 0; i < 100; ++i) {
        ::std::this_thread::sleep_for(chrono::milliseconds(1));
        t ^= i; // prevent overeager optimization
    }
    auto stop = ::std::chrono::steady_clock::now();
    auto elapsed = ::std::chrono::duration_cast<::std::chrono::milliseconds>(stop - start);
    ::std::cout << elapsed.count() << "\n";
    ::std::cerr << t << "\n";

  return 0;
}

它可以使用以下命令进行编译:

cl /EHsc /std:c++17 /O2 sleep_for.cpp winmm.lib

谢谢,杰里米!

附:增加计时器频率有它的价格:https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

© www.soinside.com 2019 - 2024. All rights reserved.