我正在使用qt5和c ++在Windows 10中为某些复杂的通信应用程序编写一个计时器。我想使用微秒分辨率的最大3%的CPU。
最初,我在此应用中使用了qTimer(qt5)。 CPU使用率低且开发人员友好的界面很好。但这不是我所需要的精确。它仅需要毫秒作为参数,但我需要微秒。在许多实际情况下,例如cpu上的重载,计时器的精度并不等于此分辨率。有时计时器会在1毫秒(有时是15毫秒)内触发。您可以在图片中看到此问题:
我搜索了几天的解决方案。但是最后我发现Windows是非实时操作系统(RTOS),并且没有提供高分辨率和精确的计时器。
我为此目的编写了自己的具有CPU轮询功能的高分辨率精确计时器。我开发了在单独线程中工作的单例类。它以10微秒的分辨率工作。
但是它消耗了CPU中的一个逻辑核心。相当于ryzen 2700的6.25%。
对于我的应用程序,此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毫秒。
答案 0 :(得分:1)
我将直接引用Windows API,而不是Qt抽象。
我不认为您想降低线程优先级,我想提高线程优先级,并在轮询之间使用最少的睡眠时间来平衡延迟和CPU开销。
两个想法:
在Windows Vista中,他们专门引入了Multimedia Class Scheduler Service,以便他们可以将Windows音频组件移出内核模式并以用户模式运行,而不会影响专业音频工具。这可能会对您有所帮助-并非精确地保证了“实时”,但这意味着低延迟操作。
采用经典方式-在使用几毫秒的合理睡眠语句的同时,将您的进程和线程优先级提高到较高或较高。也就是说,将您的thread priority提高到THREAD_PRIORITY_TIME_CRITICAL
。然后在完成for
循环之后执行一个很小的Sleep。该睡眠时间应在0..10毫秒之间。需要进行一些实验,但是到下一次预期的超时时间,我最多睡不到一半的时间,最多10毫秒。当您在计时器的N毫秒内时,您可能需要旋转而不是屈服。需要一些实验。您也可以尝试将Process priority提高到REALTIME_PRIORITY_CLASS
。
要小心-处于这些较高优先级的几个失控的进程和线程没有进入睡眠状态,就会锁定系统。