处理C ++中许多进程的中央数据缓冲区

时间:2009-10-19 19:58:07

标签: c++ events buffering

我遇到了以下问题,无法决定如何继续:

我有一个类Reader,每1 / T秒获取一块数据(实际上数据来自视频帧,每秒30帧)。这些块将被传递给多个对象Detectors,这些对象处理块并输出决策。然而,在做出决定之前每个探测器需要读取的块的数量变化,例如,有些可能只需要一个大块,大约51个。

我正在考虑建立一个数据缓冲区,其中Reader放置读取数据块,实现发布/订阅者注册每个Detector并在数据中有足够数量的帧时向其发送信号缓冲区供它处理。这是一个好方法吗?另外,管理缓冲区的最佳方法是什么,让Detectors从中读取数据而不制作自己的副本?共享指针?

非常感谢!

C

3 个答案:

答案 0 :(得分:4)

我会调查ring buffer/circular queue。这将允许您只使用一次性内存分配来执行您想要的操作(前提是您使初始缓冲区大小足以容纳最大必需帧数)。

至于管理对缓冲区的访问,在数据准备就绪时发出信号并与阅读器共享指针将起作用,但如果你使用多个线程,则需要某种类型的同步,c.f。 produced-consumer problem

答案 1 :(得分:2)

我最近实现了一些类似于你所描述的东西。

我强烈推荐使用boost :: interprocess库(boost.org获取更多信息)。

您正在寻找的是boost :: interprocess / managed_shared_memory。一开始看起来有点奇怪,但是一旦掌握了它,你就会喜欢它。

您要做的是:创建托管共享内存段。使用void_allocator(查找分配器)分配将要处理进程间通信的对象。实现同步机制(例如,boost :: interprocess:semaphore& boost :: interprocess_mutex)。通过托管共享内存实现来自不同进程的通信。

答案 2 :(得分:2)

我认为(也基于您对Maciek的评论)您必须首先了解线程和流程之间的区别以及它们如何进行通信。

关于设计问题: 尝试从简单的设计开始。例如,仅使用线程并使用它自己的同步队列*将每个订阅者的shared_ptr传递给作业。由于对数据的访问是只读的,并且AFAICR,boost :: shared_ptr对于这种用途是多线程安全的,因此没有同步问题并且数据被自动清理。不要担心内存实现(还),请确保每个订阅者/线程使用有限数量的内存(o(1))(如您所说,最多约51个shared_ptrs)。

当您拥有这个工作骨架时,您将能够根据遇到的问题开始优化。如果问题是重新定位,您可以移动到环形缓冲区(如bcat所示)。或者您可以用池分配器替换您的分配器(/ new运算符)。如果您有许多订阅者,将队列合并为所有线程使用的单个队列可能是有效的。这样做需要更多的信息(如果一个线程由于非常长的计算而非常慢?你有什么方法可以发信号来停止处理吗?或者队列是否会增长?如果是这种情况,循环缓冲区可能无法工作很好......)并且可能有它的复杂性,但请记住我们只是试图保存shared_ptrs占用的空间(而不是工作)。

底线,尽量避免过早优化。相反,在设计中使用合理的优化和可扩展性来编写它,并根据您学到的内容继续进行。

祝你好运

* synchronized queue - 线程之间的队列。 push(j)添加作业,pop()等待,直到队列不为空,返回最高作业(与stl :: queue不同。当多个线程读取队列时,这很重要)。我通常通过包装stl :: queue并使用boost :: mutex保护它来实现它。