2016-10-14 2 views
0

Это мой код, используя 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() каждый раз, что вызывает высокую загрузку процессора. По этой причине я засыпаю около 880 миллисекунд, чтобы он не вызывал t.get(), пока это не нужно.

Как я уже говорил, в настоящее время я использую Sleep, чтобы сделать трюк, но я беспокоюсь о точности Sleep. Я где-то читал, что фактические миллисекунды пауз программы могут варьироваться - от 20 до 50 мс - причина, по которой я установил параметр 880. Я хочу как можно больше сократить использование ЦП; Я хочу, если возможно, приостановить более 990 миллисекунд EDIT: и все же менее 1000 миллисекунд между каждым циклом. Каким будет лучший способ?

+0

Лучший способ пойти бы бросить, опираясь на точные моменты времени в Windows. Это не было надумано с учетом этого. Даже при плотной петле и вообще не спать, нет ничего, что помешало бы Windows перейти на другую задачу, как только вы достигнете отметки в 1 секунду. –

+0

Возможный дубликат [Как использовать API SetTimer] (http://stackoverflow.com/questions/15685095/how-to-use-settimer-api) – user3528438

+0

Это не очень хорошая стратегия, вы никогда не хотите, чтобы ОС хорошая причина, чтобы * остановить * запуск вашего кода. Вы хотите дать ему вескую причину * начать * его. Что вы можете сделать, сделав Sleep() точным, вызовите timeBeginPeriod(). Дайте ему более веские причины, вызвав SetThreadPriority(). timeSetEvent() - хороший способ получить довольно последовательный таймер, который может настраиваться на латентность, будьте осторожны, это асинхронно. Вы никогда не получите его более точным, чем 1 мс, и вы никогда не сможете предположить, что он всегда будет 1 мс. Ядро и драйверы устройства всегда будут первыми. –

ответ

-1

Если вы хотите приостановить более 990 миллисекунд, напишите спать на 991 миллисекунду. Ваша нить гарантированно будет спать, по крайней мере, так долго. Это будет не меньше, но оно может быть кратным 20-50 мс больше (в зависимости от разрешения временной разметки вашей ОС и стоимости переключения контекста).

Однако это не даст вам что-то работает «ровно каждую секунду». Этого просто невозможно достичь в операционной системе, работающей во времени. Вам придется программировать ближе к металлу или полагаться на прерывание от источника PPS и просто молиться, чтобы ваша ОС позволяла вам запускать всю свою итерацию цикла одним выстрелом. Или, я полагаю, напишу что-нибудь для запуска в режиме ядра & hellip ;?

+0

Есть ли способ получить разрешение отрезки времени моей ОС? Если будет гарантировано, что «Сон» не будет превышать определенные миллисекунды, на основе разрешения это будет достаточно для меня. – hjjg200

+1

@ hʌn: Вы даже не знаете, сколько времени потребуется дольше. Вы не можете рассчитывать на точное время в таком пространстве пользовательской операционной системы, когда-либо. ОС выбирает, когда запускать код! Он может отказаться от контроля за процессом в течение 2 часов и соблюдать все соответствующие стандарты!Как правило, вместо того, чтобы пытаться запускать код ровно каждую секунду, мы запускаем код _as рядом с каждой секундой, поскольку мы можем get_, и убедитесь, что мы скорректируем наши переменные в соответствии с тем, сколько времени прошло _actually_. См. Также: переменная частота кадров в играх –

+0

Прочитайте документацию. «Сон» может вернуться раньше. Извините, -1 за дезинформацию. – IInspectable

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?

Смежные вопросы