我正在尝试执行一个睡眠函数,这是有些准确。我测量了我的睡眠功能的睡眠时间,并把它们放在一起。以下示例的格式为:"预期ms:结果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使用率很低,但仍然不准确。
- 我曾在某处读到使用多媒体计时器可以提供准确的睡眠。
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和i99900k。
获得相当高准确度的一种方法(但不是完美的,因为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) {}
}