在多线程上下文中实施实时约束
Enforcing real-time constraint in multi-threaded context
我目前正在为一个程序开发一个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或类似的东西),并设置一个循环计时器,唤醒你的线程,例如通过信号量。
此外,将绘图与处理解耦也是一个好主意。
- 在C++中使用cURL和多线程
- 多线程双缓冲区
- 为什么我的多线程作业队列崩溃
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 为什么一个向量上的多线程操作很慢
- 学习多线程C++:添加线程不会使执行速度更快,即使它看起来应该
- 全局变量 多读取器 一个写入器多线程安全?
- boost::文件系统::recursive_directory_iterator多线程安全
- 如何阻止TensorFlow的多线程
- 如何在多线程中正确使用unique_ptr进行多态性?
- 并发/多线程:是否可以以这种方式生成相同的输出?
- sigwait() 在多线程程序中不起作用
- 多线程程序中出现意外的内存泄漏
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 多线程比没有线程C++慢
- 具有 C++11 多线程的特征库
- 使用OpenCv和多线程的IP摄像机实时视频馈送
- C++实时蛇形游戏机,无需多线程
- 在多线程上下文中实施实时约束