在多线程上下文中实施实时约束

Enforcing real-time constraint in multi-threaded context

本文关键字:实时约束 多线程 上下文      更新时间:2023-10-16

我目前正在为一个程序开发一个GUI,该程序必须轮询,处理然后实时显示数据(带图)。

我正在努力的部分是代码,在一个单独的线程中运行,实际上从一些外部硬件轮询数据,然后处理它。我想做这个工作的函数被定期调用一个固定的周期(即调用之间的1/20秒)。

我真的不知道这是否可能,以及如何强制函数必须定期调用,每秒精确20次…

在阅读了一些关于实时编程的内容后,基于我从游戏开发中学到的知识和主要游戏循环的概念,我的第一个方法是使用一个循环,它将根据轮询和处理所花费的时间来调整执行时间:

 while(running){
     //Let's assume this function get the time elapsed since
     //the program started
     int start = get_current_time_millisecond();
     //Retrieve the data from the hardware
     pollData();
     //Process the data retrieved
     processData();
     //Queue the data wherever it is needed:
     //- plotting widget of the GUI
     //- recording object
     dispatchProcessedData();
     int elapsed = get_current_time_millisecond() - start;
     int remaining = 50 - elapsed;
     if(remaining > 0){
         sleep(remaining);
     }
 }

,但这似乎是有缺陷的,因为它可能会导致漂移问题,如果在一个迭代期间经过的时间大于我想要坚持的周期。

这可能是因为计算花费了太多时间(我非常怀疑,但我没有足够的经验来确定,分析可以帮助消除这个问题,或者至少确定代码可能花费太多时间),但我也想知道,如果我运行多个线程可能会导致相同的问题,由于线程调度(再次,我对多线程很陌生,我可能完全错了)。

因此,我想问:

  • 是否有可能在实时编程(在多线程上下文中,如果相关的话)中强制执行这样的约束?
  • 在设计这类代码时,我应该遵循的主要准则是什么?

(如果我碰巧错过了关于这个主题的明显/容易找到的文档,我道歉)

谢谢!

除非您有外部可靠的中断源,否则执行这样的约束是非常困难的。

我相信你在消费者操作系统上能做的最接近的事情是:

  • 确保您正在使用实时内核(例如。使用Linux的RT补丁)来最小化时间变化。
  • 将轮询线程设置为最高优先级。
  • 只在轮询线程中进行轮询和调度,将任何处理留给低优先级线程,以便计算不影响轮询。
  • 使用高精度计时器(在Linux上你可以用纳秒而不是毫秒)来减少误差。
  • 使用无锁队列在轮询和处理线程之间进行通信,这样您就不必在轮询线程中支付互斥锁的成本(但是每秒只有20个样本,这可能无关紧要)。

至少这是我们为我们的产品所做的,它在400mhz的CPU上以100Hz (10ms)轮询。你永远不会完全摆脱这种方式的漂移,但它是非常小的。

正如@Mark建议的,最好是使用实时操作系统。

如果一种"软"RT足够好,你应该创建一个具有高优先级的线程(例如在Linux中使用调度类实时FIFO或类似的东西),并设置一个循环计时器,唤醒你的线程,例如通过信号量。

此外,将绘图与处理解耦也是一个好主意。