简体   繁体   中英

Precise way to reduce CPU usage in an infinite loop

This is my code using QueryPeformanceCounter as timer.

//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 );
    }
}

Without Sleep this loop would go on indefinitely calling t.get() every time which causes high CPU usage. For that reason, I make it sleep for about 880 milliseconds so that it wouldn't call t.get() while not necessary.

As I said above, I'm currently using Sleep to do the trick, but what I'm worried about is the accuracy of Sleep . I've read somewhere that the actual milliseconds the program pauses may vary - 20 to 50 ms - the reason I set the parameter to 880 . I want to reduce the CPU usage as much as possible; I want to, if possible, pause more than 990 milliseconds EDIT: and yet less than 1000 milliseconds between every loop. What would be the best way to go?

I don't get why you are calling t.start() twice (it resets the clock?), but I would like to propose a kind of solution for the Sleep inaccuracy. Let's take a look at the content of while( running ) loop and follow the algorithm:

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);
}

The value of sleep_precision should be set empirically - OSes I know can't give you that.

Next, there are some alternatives of the sleeping mechanism that may better suit your needs - Is there an alternative for sleep() in C?

If you want to pause more than 990 milliseconds, write a sleep for 991 milliseconds. Your thread is guaranteed to be asleep for at least that long. It won't be less, but it could be multiples of 20-50ms more (depending on the resolution of your OS's time slicing, and on the the cost of context switching).

However, this will not give you something running "exactly every second". There is just no way to achieve that on a time-shared operating system. You'll have to program closer to the metal, or rely on an interrupt from a PPS source and just pray your OS lets you run your entire loop iteration in one shot. Or, I suppose, write something to run in kernel mode…?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM