Как уменьшить использование процессора высокоточным таймером с высоким разрешением (10 микросекунд)? - PullRequest
0 голосов
/ 21 апреля 2019

Я пишу таймер для некоторых сложных коммуникационных приложений в Windows 10 с qt5 и c ++. Я хочу использовать максимум 3 процента процессора с микросекундным разрешением.

Изначально я использовал qTimer (qt5) в этом приложении. Это было хорошо с низким использованием процессора и дружественным интерфейсом для разработчиков. Но это было не совсем так, как мне нужно. Это всего лишь миллисекунда в качестве параметра, но мне нужна микросекунда. И точность таймера не была равна этому разрешению во многих реальных ситуациях, таких как большая нагрузка на процессор. Иногда таймер срабатывает со скоростью 1 миллисекунда, иногда 15 миллисекунд. Вы можете увидеть эту проблему на картинке:

enter image description here

Я искал решение в течение нескольких дней. Но в конце концов я обнаружил, что Windows не является операционной системой реального времени (RTOS) и не дает высокого разрешения и точного таймера.

Я написал собственный точный таймер высокого разрешения с опросом процессора для этой цели. Я разработал синглтон-класс, работающий в отдельной ветке. Он работает с разрешением 10 микросекунд.

enter image description here

Но он потребляет одно логическое ядро ​​в процессоре. Эквивалент 6,25% при ризене 2700.

enter image description here

Для моего приложения это использование ЦП недопустимо. Как я могу уменьшить использование этого процессора, не отдавая высокое разрешение?

Это код, который выполняет работу:

void CsPreciseTimerThread::run()
{

while (true)
{
    QMutexLocker locker(&mMutex);
    for (int i=0;i<mTimerList.size();i++) 
    {
        CsPreciseTimerMiddleLayer* timer = mTimerList[i];
        int interval = timer->getInterval();
        if ( (timer->isActive() == true&&timer->remainingTime()<0))
        {
            timer->emitTimeout();
            timer->resetTime();
        }
    }



}
}

Я попытался уменьшить приоритет потока таймера. Я использовал эти строки:

QThread::start(QThread::Priority::LowestPriority);

И это:

QThread::start(QThread::Priority::IdlePriority);

Эти изменения делают таймер менее точным, но загрузка процессора не уменьшается.

После этого я попытался заставить текущий поток спать в течение нескольких микросекунд в цикле.

QThread::usleep(15);

Как вы могли догадаться, функция сна действительно испортила точность. Иногда таймер спит дольше, чем ожидалось, например, 10 мс или 15 мс.

1 Ответ

1 голос
/ 21 апреля 2019

Я собираюсь ссылаться на API-интерфейсы Windows напрямую, а не на абстракции Qt.

Я не думаю, что вы хотите снизить приоритет потока, я думаю, что вы хотите повысить приоритет потока и использовать наименьшийколичество спящих между опросами, чтобы балансировать между задержкой и нагрузкой на процессор.

Две идеи:

  1. В Windows Vista они представили Multimedia Class Scheduler Service специально для того, чтобы они могли вывести аудио компоненты Windows из режима ядра и работать в пользовательском режиме, не влияя на про-аудио инструменты.Это, вероятно, будет полезно для вас - это не гарантировано точно "в реальном времени", но оно предназначено для операций с низкой задержкой.

  2. Идя классическим путем - повысите ваш процесс и приоритет потока довысокий или критический, при использовании разумного выражения сна в течение нескольких миллисекунд.То есть увеличьте приоритет до THREAD_PRIORITY_TIME_CRITICAL.Затем выполните очень маленький Sleep после завершения цикла for.Это количество сна должно быть между 0,10 миллисекундами.Требуются некоторые эксперименты, но я буду спать не больше половины времени до следующего ожидаемого времени ожидания, максимум 10 мс.И когда вы находитесь в пределах N микросекунд от вашего таймера, вам, возможно, придется просто вращаться, а не уступать.Некоторое экспериментирование требуется.Вы также можете поэкспериментировать с повышением Приоритета процесса до REALTIME_PRIORITY_CLASS.

Будьте осторожны - Несколько запущенных процессов и потоков с этими более высокими уровнями приоритета, которые не спят, могут заблокировать систему.

...