3

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

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

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

非常感谢!

C

4

3 回答 3

4

我会研究一个环形缓冲区/循环队列。这将允许您只使用一次性内存分配来做您想做的事情(前提是您使初始缓冲区大小足够大以容纳最大必要的帧数)。

至于管理对缓冲区的访问,在数据准备好时发出信号并与读取器共享指针将起作用,但是如果您使用多个线程,则需要某种类型的同步,参见生产者-消费者问题

于 2009-10-19T20:07:12.260 回答
2

我最近实现了与您所描述的类似的东西。

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

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

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

于 2009-10-19T21:12:44.930 回答
2

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

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

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

底线,尽量避免过早的优化。取而代之的是,在设计中以合理的优化和可扩展性编写它,然后根据您所学的内容从那里继续。

祝你好运

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

于 2009-10-19T23:39:38.563 回答