在无限循环中降低CPU使用率的精确方法

时间:2016-10-14 15:19:56

标签: c++ windows infinite-loop cpu-usage

这是我使用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毫秒编辑:但小于1000毫秒。什么是最好的方式?

2 个答案:

答案 0 :(得分:0)

我不明白为什么你要两次调用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的值应该根据经验设定 - 我认识的操作系统不能给你这个。

接下来,有一些替代的睡眠机制可能更适合您的需求 - Is there an alternative for sleep() in C?

答案 1 :(得分:-1)

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

然而,这不会给你“正好每一秒”运行的东西。在分时操作系统上无法实现这一点。您必须更接近金属编程,或依赖PPS源的中断,并祈祷您的操作系统允许您一次性运行整个循环迭代。或者,我想,写一些在内核模式下运行的东西......?