如何减少高分辨率(10微秒)精确计时器的CPU使用率?

时间:2019-04-21 18:05:53

标签: c++ qt timer qt5 qtimer

我正在使用qt5和c ++在Windows 10中为某些复杂的通信应用程序编写一个计时器。我想使用微秒分辨率的最大3%的CPU。

最初,我在此应用中使用了qTimer(qt5)。 CPU使用率低且开发人员友好的界面很好。但这不是我所需要的精确。它仅需要毫秒作为参数,但我需要微秒。在许多实际情况下,例如cpu上的重载,计时器的精度并不等于此分辨率。有时计时器会在1毫秒(有时是15毫秒)内触发。您可以在图片中看到此问题:

enter image description here

我搜索了几天的解决方案。但是最后我发现Windows是非实时操作系统(RTOS),并且没有提供高分辨率和精确的计时器。

我为此目的编写了自己的具有CPU轮询功能的高分辨率精确计时器。我开发了在单独线程中工作的单例类。它以10微秒的分辨率工作。

enter image description here

但是它消耗了CPU中的一个逻辑核心。相当于ryzen 2700的6.25%。

enter image description here

对于我的应用程序,此CPU使用率是不可接受的。 如何在不放弃高分辨率的情况下减少CPU使用率?

这是完成任务的代码:

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

此更改使计时器的精度降低,但CPU使用率并未降低。

之后,我尝试强制当前线程在循环中休眠几微秒。

QThread::usleep(15);

您可能会认为睡眠功能确实提高了准确性。有时计时器的睡眠时间比预期的要长,例如10毫秒或15毫秒。

1 个答案:

答案 0 :(得分:1)

我将直接引用Windows API,而不是Qt抽象。

我不认为您想降低线程优先级,我想提高线程优先级,并在轮询之间使用最少的睡眠时间来平衡延迟和CPU开销。

两个想法:

  1. 在Windows Vista中,他们专门引入了Multimedia Class Scheduler Service,以便他们可以将Windows音频组件移出内核模式并以用户模式运行,而不会影响专业音频工具。这可能会对您有所帮助-并非精确地保证了“实时”,但这意味着低延迟操作。

  2. 采用经典方式-在使用几毫秒的合理睡眠​​语句的同时,将您的进程和线程优先级提高到较高或较高。也就是说,将您的thread priority提高到THREAD_PRIORITY_TIME_CRITICAL。然后在完成for循环之后执行一个很小的Sleep。该睡眠时间应在0..10毫秒之间。需要进行一些实验,但是到下一次预期的超时时间,我最多睡不到一半的时间,最多10毫秒。当您在计时器的N毫秒内时,您可能需要旋转而不是屈服。需要一些实验。您也可以尝试将Process priority提高到REALTIME_PRIORITY_CLASS

要小心-处于这些较高优先级的几个失控的进程和线程没有进入睡眠状态,就会锁定系统。