代码之家  ›  专栏  ›  技术社区  ›  Abbas Perçin

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

  •  0
  • Abbas Perçin  · 技术社区  · 5 年前

    我正在编写一个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中消耗一个逻辑核。相当于瑞森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毫秒。

    0 回复  |  直到 5 年前
        1
  •  3
  •   selbie    5 年前

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

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

    两个想法:

    1. 在Windows Vista中,他们引入了 Multimedia Class Scheduler Service 特别是,他们可以将Windows音频组件移出内核模式,并在用户模式下运行,而不会影响pro audio工具。这可能会对你有所帮助——它不是精确的“实时”保护,但它是为低延迟操作设计的。

    2. 按照经典的方式——将进程和线程的优先级提高到高或关键级别,同时使用几毫秒的合理睡眠语句。也就是说,举起手来 thread priority THREAD_PRIORITY_TIME_CRITICAL .然后做一个非常小的 Sleep 工程竣工后 for 环这个睡眠量应该在0到0之间。。10毫秒。需要进行一些实验,但在下一个预期超时之前,我的睡眠时间不会超过一半,最多10毫秒。当你的计时器在N微秒之内时,你可能需要旋转而不是屈服。需要进行一些实验。你也可以尝试提高你的体重 Process priority REALTIME_PRIORITY_CLASS .

    小心 -少数处于这些更高优先级且未休眠的失控进程和线程可能会锁定系统。