【问题标题】:C++ Sleep functionsC++ 睡眠函数
【发布时间】:2021-05-11 12:01:45
【问题描述】:

我正在尝试执行一个有点准确的睡眠功能。我测量了我的睡眠功能睡了多长时间并将它们并排放置。下面示例的格式为:“expected ms:outcome ms”。

我尝试了很多选项,但仍然找不到解决方案。以下是我尝试过的路线:

路线 1

Sleep(<time>)
/* milliseconds */
38.4344 46.4354
41.728 47.7818
0.556 0.0012
43.6532 46.8087
0.4523 0.0009
62.8664 76.995
1.5363 15.4592
75.9435 78.1663
91.5194 92.0786
0.6533 0.001
39.7423 45.6729
0.5022 0.0008
54.7837 60.597
0.4248 0.0011
39.2165 45.6977
0.4854 0.0008
10.6741 15.054
  • 几乎没有明显的 CPU 使用率,这很好,但结果仍然不准确。

路线 2

/* Windows sleep in 100ns units */
BOOLEAN nanosleep(LONGLONG ns){
    /* Declarations */
    HANDLE timer;   /* Timer handle */
    LARGE_INTEGER li;   /* Time defintion */
    /* Create timer */
    if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL)))
        return FALSE;
    /* Set timer properties */
    li.QuadPart = -ns;
    if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){
        CloseHandle(timer);
        return FALSE;
    }
    /* Start & wait for timer */
    WaitForSingleObject(timer, INFINITE);
    /* Clean resources */
    CloseHandle(timer);
    /* Slept without problems */
    return TRUE;
}
/* milliseconds */
1.057 14.7561
66.5977 79.4437
0.409 14.7597
152.053 156.757
1.26725 15.747
19.025 30.6343
67.3235 78.678
0.4203 14.4713
65.3507 74.4703
0.4525 14.8102
28.6145 29.7099
72.0035 74.7315
0.5971 14.8625
55.7059 59.3889
0.4791 14.5419
50.9913 61.6719
0.5929 15.5558
  • CPU 使用率较低,这很好,但仍然不准确。
  • 我曾在某处读到使用多媒体定时器可以提供准确的睡眠。

Code Source

路线 3

void super_sleep(double ms)
{
    auto a = std::chrono::steady_clock::now();
    while ((std::chrono::steady_clock::now() - a) < std::chrono::milliseconds(static_cast<int>(ms))) {
        continue;
    }
}
/* milliseconds */
55.7059 55.0006
0.5669 0.0008
66.5977 66.0009
0.4213 0.0009
0.7228 0.0007
7.5374 7.0006
0.8825 0.0007
0.4143 0.0009
59.8062 59.0005
51.7157 51.0006
54.0807 54.0006
11.8834 11.0006
65.3507 65.0004
14.429 14.0006
0.4452 0.0012
1.6797 1.0004
96.0012 96.0006
  • 工作得比其他尝试好很多,但占用了我高达 7% 的 CPU。

我也尝试使用std::this_thread::sleep_for() 并收到与Route 2 相似的结果。

我使用的是 Windows 10 20H2、C++17 和 i9 9900k。

【问题讨论】:

  • 要获得有保证的 CPU 实时指标,如果您希望程序“准确”地休眠一段时间,则需要使用特殊用途、专用的实时操作系统。 Microsoft Windows 不是实时操作系统。
  • Windows 10 不是实时操作系统。甚至实时操作系统也不是完全准确的。你想达到什么目的。第二个问题,真正需要实现的目标(通常少于开发人员的目标)
  • 粗略的轮廓 - Sleep 放弃线程的时间片并将其挂起。仅当至少经过请求的时间量(或更长)时,才会唤醒线程。如果他们没有可用于运行线程的处理器,它将排队,直到有一个可用。这里的一些背景:randomascii.wordpress.com/2020/10/04/…
  • 我使用了这个Timer,它声称使用 Win32 高性能/分辨率计时器 API。我的代码看起来像win32::Stopwatch t; t.Start(); Sleep(delay_entry.second + slope); t.Stop();

标签: c++ windows-10 sleep


【解决方案1】:

获得相当良好准确性的一种方法(但并不完美,因为 Windows 不是实时操作系统)是使用标准睡眠功能之一,但睡眠时间短 - 然后忙 -等待剩余时间。这通常会使 CPU 使用率保持在较低水平。

template<class T, class U>
void Sleep(std::chrono::duration<T,U> ss) {
    auto target = std::chrono::steady_clock::now() + ss; // the target end time

    // Sleep short. 5 ms is just an example. You need to trim that parameter.
    std::this_thread::sleep_until(target - std::chrono::milliseconds(5));

    // busy-wait the remaining time
    while(std::chrono::steady_clock::now() < target) {}
}

【讨论】:

  • 我会试试这个然后更新你,谢谢
  • @Clawifier 好的。请记住修剪这 5 毫秒。这个想法是它应该总是now() &lt; targettrue 时唤醒,否则准确度将无法达到应有的水平。
  • 这在保持 CPU 使用率的同时提供了更准确的睡眠,谢谢!
猜你喜欢
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多