精确地减少无限循环中的CPU使用

Precise way to reduce CPU usage in an infinite loop

本文关键字:CPU 使用 无限循环      更新时间:2023-10-16

这是我使用QueryPeformanceCounter作为定时器的代码。

//timer.h
class timer {
private:
    ...
public:
    ...
    double get(); //returns elapsed time in seconds
    void start();
};
//a.cpp
void loop() {
    timer t;
    double tick;
    double diff; //surplus seconds
    t.start();
    while( running ) {
        tick = t.get();
        if( tick >= 1.0 - diff ) {
            t.start();
            //things that should be run exactly every second
            ...
        }
        Sleep( 880 );
    }
}

如果没有Sleep,这个循环每次都会无限地调用t.get(),这会导致高CPU使用率。出于这个原因,我让它休眠大约880毫秒,这样它就不会调用t.get(),而不是必要的。

正如我上面所说的,我目前使用Sleep来完成这个技巧,但我担心的是Sleep的准确性。我在某个地方读到,程序暂停的实际毫秒数可能会变化- 20到50毫秒-这就是我将参数设置为880的原因。我想尽可能地减少CPU的使用;如果可能的话,我希望在每个循环之间暂停超过990毫秒EDIT:但小于1000毫秒。最好的办法是什么?

我不明白为什么你要调用t.start()两次(它重置时钟?),但我想为Sleep不准确提出一种解决方案。让我们看一下while( running )循环的内容,并遵循算法:

double future, remaining, sleep_precision = 0.05;
while (running) {
    future = t.get() + 1.0;
    things_that_should_be_run_exactly_every_second();
    // the loop in case of spurious wakeup
    for (;;) {
        remaining = future - t.get();
        if (remaining < sleep_precision) break;
        Sleep(remaining);
    }
    // next, do the spin-lock for at most sleep_precision
    while (t.get() < future);
}

sleep_precision的值应该根据经验设置——我知道的操作系统不能给你这个。

接下来,有一些睡眠机制的替代方案可能更适合您的需求-在C中是否有sleep()的替代方案?

如果您想要暂停超过990毫秒,则写入991毫秒的睡眠。您的线程保证至少在那么长时间内处于休眠状态。它不会更少,但它可能是20-50ms 的倍数(取决于操作系统的时间切片的分辨率,以及上下文切换的成本)。

然而,这不会给你一些"精确每秒"运行的东西。这在分时操作系统上是无法实现的。你将不得不编程更接近金属,或者依赖于PPS源的中断,并祈祷你的操作系统允许你一次运行整个循环迭代。或者,我想,写一些东西在内核模式下运行&帮助;