我有一个程序,其中的等待/延迟必须准确。我遇到的问题是不同计算机上的等待/延迟更改(我了解cpu频率差异可能会导致此问题),我想知道是否有人可以将我指向正确的方向,以便我可以找到准确的跨计算机睡眠/等待时间。我也知道在Windows操作系统上不可能达到1ms的精度,因为它不是实时的,CPU使用率也是一个问题,因此我宁可不要热睡眠。 (c ++ lang)
static void SleepShort(float milliseconds) {
static bool once = true;
if (once) {
ULONG actualResolution;
ZwSetTimerResolution(1, true, &actualResolution);
once = false;
}
LARGE_INTEGER interval;
interval.QuadPart = -1 * (int)((milliseconds - 0.516) * 10000.0f);
NtDelayExecution(false, &interval);
}
我在一个类似的问题上发现了这个
interval.QuadPart = -1 * (int)((milliseconds - 0.516) * 10000.0f);
-0.516似乎至少可以准确地反映我在计算机上所做的事情。此等待/睡眠用于1ms睡眠。
#include <chrono>
全球空间:
class bla{
double time;
std::chrono::steady_clock::time_point start_clock;
void upd_clock(){
std::chrono::steady_clock::time_point current_time = std::chrono::steady_clock::now();
time = ((double) std::chrono::duration_cast<std::chrono::miliseconds>(current_time - start_clock).count())/1000;
}
}
在主要:
bla->start_clock = std::chrono::steady_clock::now();
在主循环中:
while(1){
bla->upd_clock();
}
bla-> time存储时间。试用毫秒/微秒等。这是您测量时间的方式。如果它进入睡眠状态-不要让线程进入睡眠状态-醒来将比您的目标花费更长的时间。您可以仅使用更新时钟和检查时间功能来保持主线程运行。还有一件事:在类似的时间测量间隔内,您可以使用int64而不是double来编写它。
如果可能,我建议使用<chrono>
,因为它会在编译时为您捕获很多错误,并使逻辑更容易。
接下来,我建议结合使用操作系统进行睡眠和“热睡眠”。简而言之,请使用操作系统进入睡眠状态,直到达到所需的唤醒时间之前的短时间间隔,然后再旋转最后一个小的时间间隔。我在最后一次旋转间隔ymmv中使用了1ms。
#include <chrono>
#include <iostream>
#include <thread>
void
SleepShort(std::chrono::duration<float, std::milli> d)
{
using namespace std::chrono;
auto t = steady_clock::now() + ceil<steady_clock::duration>(d);
if (d > 1ms)
std::this_thread::sleep_until(t-1ms);
while (steady_clock::now() < t)
;
}
我在开发上述代码时遇到的一个难题是避免float
中缺乏必要的精度。我最初有以下代码:
auto t = steady_clock::now() + d;
隐式创建一个time_point
,其中rep
为float
,周期为nanoseconds
,用于测量自计算机启动以来(在我的平台上)的持续时间。事实证明float
不具有表示该数量所必需的精度。随后,我的旋转循环无法正常工作。
如图所示切换为ceil
,会将浮点毫秒转换为steady_clock
使用的基于整数的滴答(在所有3个主要实现中为nanoseconds
),现在该算法具有足够的精度以正确操作。 Fwiw,double
也可以正常工作。
可以这样称呼:
SleepShort(2.5ms);