5

我有一个产生数据流的仪器;我的代码通过回调访问这些数据onDataAcquisitionEvent(const InstrumentOutput &data)。数据处理算法可能比数据到达的速度慢得多,所以我不能希望处理每一条数据(我也不必),但希望处理尽可能多的数据。感谢该仪器作为环境传感器,具有我无法控制的数据采集速率。InstrumentOutput例如,可以是一个包含不同位置的三个同时压力测量值的类。

我还需要保留一些简短的数据历史记录。例如,假设我可以合理地希望每 200 毫秒左右处理一次数据样本。大多数时候,我很乐意只处理最后一个样本,但有时我需要查看在最新样本之前到达的几秒钟的数据,具体取决于最后一个样本中是否存在异常读数。

另一个要求是尽快退出onDataAcquisitionEvent()回调,以避免传感器中的数据丢失。

数据采集​​库(第三方)在单独的线程上收集仪器数据。

我想到了以下设计;拥有单个生产者/单个消费者队列,并将数据令牌推送到 onDataAcquisitionEvent() 回调中的同步队列中。
在接收端,有一个循环从队列中弹出数据。由于数据到达率很高,循环几乎永远不会休眠。在每次迭代中,都会发生以下情况:

  1. 从队列中弹出所有可用数据,
  2. 弹出的数据被复制到一个循环缓冲区(我使用了 boost 循环缓冲区),这样一些历史总是可用的,
  3. 处理缓冲区中的最后一个元素(并可能查看之前的元素),
  4. 重复循环。

问题:

  1. 这种设计是否合理,有哪些陷阱?和
  2. 有什么更好的设计?

编辑:我想到的一个问题是当循环缓冲区的大小不足以容纳所需的历史时;目前我只是重新分配循环缓冲区,使其大小增加一倍。我希望我只需要这样做一两次。

4

3 回答 3

3

我在数据采集方面有一点经验,我可以告诉你很多开发人员都存在过早的特性蠕变问题。因为简单地将仪器中的数据捕获到日志中听起来很容易,所以人们倾向于在验证日志记录是否确实可靠之前向系统添加不必要的组件。这是一个大错误。

另一个要求是尽快退出onDataAcquisitionEvent()回调,以避免传感器中的数据丢失。

这是产品的该部分在所有现场条件下都能 110% 工作之前的唯一要求。


大多数时候,我很乐意只处理最后一个样本,但有时我需要查看在最新样本之前到达的几秒钟的数据,具体取决于最后一个样本中是否存在异常读数。

“大多数时候”并不重要。最坏情况下的代码,因为onDataAcquisitionEvent()不能花时间考虑突发事件。

听起来你陷入了设计它以使用可能可用的最佳数据的陷阱,并且如果它不可用或者如果向监视器提供最佳数据最终过于昂贵,可能会发生什么。

从源头抽取数据。指定异常案例处理需要多少样本,并尝试以恒定的采样率提供那么多样本,再加上 20% 的余量。

当然不应该有永不休眠的循环。循环缓冲区很好,但只需使用所需的最小值填充它,并仅根据需要频繁分析它。

系统的质量由其决定稳定性和确定性,而不是试图加倍努力并提供尽可能多的东西。

于 2012-07-22T03:18:37.127 回答
0

您的生产者/消费者设计正是正确的设计。在实时系统中,我们通常还为消费线程提供不同的运行时优先级,不确定这是否适用于您的情况。

使用基本上是双向链表的数据结构,这样如果它增长,您不需要重新分配所有内容,并且您还可以 O(1) 访问所需的样本。

如果您的内存不够大,无法容纳几秒钟的数据(它应该 - 每 200 毫秒一个样本?每秒 5 个样本。)那么您需要看看您是否可以忍受从辅助内存中读取,但这就是吞吐量并且在您的情况下,与您对“尽快退出回调”的设计和要求无关。

考虑一个不需要锁定的队列实现(记住:只有单个读取器和单个写入器!),这样您的回调就不会停止。

如果你的回调真的很快,考虑禁用中断/给它一个高优先级。如果它永远不会阻塞并且设置了正确的优先级,则可能没有必要。

于 2012-07-22T04:18:16.780 回答
0

问题,(1)这个设计听起来不错,有什么陷阱,以及(2)什么是更好的设计。谢谢。

是的,它是健全的。但出于性能原因,您应该设计代码,使其在每个处理阶段处理一组输入样本,而不是每个处理一个样本。这为当前最先进的 CPU 提供了更优化的代码。

这样一个数组(=一块数据)的长度是固定的(更简单的代码)或可变的(灵活的,但某些处理可能会变得更复杂)。

作为第二个设计选择,您可能应该忽略此架构级别的历史,并将该功能降级...

大多数时候,我很乐意只处理最后一个样本,但有时我需要查看几秒钟的数据 [...]

也许,跟踪历史记录应该在代码的那个特殊部分中实现,偶尔需要访问它。也许,这不应该是“整体架构”的一部分。如果是这样,它就完全简化了处理。

于 2012-07-22T05:25:49.123 回答