3

我正在尝试创建一个数据缓冲区,更具体地说,是一个图像缓冲区,它将在多个模块之间共享。这些模块只从缓冲区读取,根本不相互通信。我的困难是:

1.数据量大:

每个图像大于 10M,这意味着不希望为不同的线程复制这些数据

2.我不希望记忆变得疯狂:

随着新数据的不断涌入(实时),非常旧的数据必须在所有模块使用完毕后删除。

然而,为了让事情变得更加复杂,那些消耗数据的模块的速度不同:有些更快/更慢,有些需要更多数据(多张图像)才能获得结果,有些需要更少(只有一张图像)

我一直在考虑使用 shared_ptr 来解决第一个问题:创建一个 boost shared_ptr(s) 的队列,每个 shared_ptr() 指向一个图像(char 数组)。然后将这些指针的子集传递给不同的模块。

我是这个智能指针领域的新手。什么是解决这个问题的好方法?

谢谢。

4

6 回答 6

3

Boost 共享指针正是我要建议的。是的,让指针类为您完成工作。

请注意,如果要存储数组指针,您将需要使用boost::shared_array而不是 shared_ptr。

shared_array类模板存储一个指向动态分配数组的指针。(动态分配的数组使用 C++表达式分配。)指向的对象在最后一个指向它的对象被销毁或重置new[]时保证被删除。shared_array

于 2009-10-21T04:43:40.813 回答
2

假设您在shared_ptr创建缓冲区后立即将 s 交给模块,那么它们非常适合。在这种情况下,您甚至不需要集中存储它们。

但是,如果您在某一点创建缓冲区并且稍后仅在其他点创建缓冲区,则它会变得更加复杂。
在这种情况下,您必须弄清楚您想要什么行为。
您想保留缓冲区一段时间吗?或者直到至少一个模块使用了它们?或者直到一些新数据出现?

评论集成:
由于您希望所有阅读器/模块处理所有传入数据,您可以简单地给它们一个输入队列。在传入数据上,只需将模块shared_ptr/shared_array交给新缓冲区,将它们添加到队列中。
记住要处理队列访问的多线程问题。

于 2009-10-21T04:46:18.843 回答
1

根据您的要求,我认为您可以使用两个原则:

  • shared_array<char>它将处理多线程同步和内存处理
  • 每个模块一个队列:这是必要的,因为每个模块都以自己的速度处理图像

然后,一旦你得到一个图像,你就将它分配到一个shared_array<char>. 然后在所有队列中复制该指针。

每个队列都需要单独同步,但这是一个经典的消费者/生产者的事情,所以你可能会(非常)轻松地对其进行编程,特别是因为每个队列只有一个生产者(接收图像的线程)和一个消费者。

举个例子:让我们采用 3 个模块,一个是快速的,一个是中等的,最后一个使用 3 x 3 的图像。

=> receiving image 1
module a: ['1'] -> processing (none)
module b: ['1'] -> processing (none)
module c: ['1'] -> processing (none)

=> modules a, b starts treatment of '1'
module a: [] -> processing '1'
module b: [] -> processing '1'
module c: ['1'] -> processing (none)

=> receiving image 2
module a: ['2'] -> processing '1'
module b: ['2'] -> processing '1'
module c: ['2', '1'] -> processing (none)

=> module a finishes treatment of '1', starts treatment of '2'
module a: [] -> processing '2'
module b: ['2'] -> processing '1'
module c: ['2', '1'] -> processing (none)

=> receiving image 3
module a: ['3'] -> processing '2'
module b: ['3', '2'] -> processing '1'
module c: ['3', '2', '1'] -> processing (none)

=> module c starts treatment of '1', '2' and '3'
module a: ['3'] -> processing '2'
module b: ['3', '2'] -> processing '1'
module c: [] -> processing '1', '2' and '3'

=> module a finishes treatment of '2', starts treatment of '3'
=> module b finishes treatment of '1', starts treatment of '2'
=> module c finishes treatment of '1' and '2', keeps '3' for future batch
module a: [] -> processing '3'
module b: ['3'] -> processing '2'
module c: [] -> processing '3' (waiting)

--> at this point '1' is deleted from memory

如果每个模块(线程)在“池”中注册其队列,您甚至可以使这个“简单”。

我还建议发信号,我一直认为最好让生产者发信号表明已插入新项目(如果队列为空),让消费者线程不断轮询队列......

于 2009-10-21T08:03:32.890 回答
0

1.数据量大:

您选择将图像数据存储在堆分配的缓冲区中,然后在处理模块之间传递指向它们的指针是正确的。

2.我不想让记忆变得疯狂

如果您使用 shared_ptr(),则不必使用队列进行内存管理。设计您的模块以在需要访问数据时创建/接受 shared_ptr(),并在完成后删除 shared_ptr()。shared_ptr() 的目的是当没有更多对它的引用时,指针所拥有的堆内存被删除。

于 2009-10-21T04:49:06.063 回答
0

将图像保存到文件中,以便您可以尝试将 posix 文件映射映射到每个图像的内存。映射后,您可以将其作为共享内存,即使在多进程之间也可以有效使用。

顺便说一句:您的系统是否支持 posix 文件映射?例如 Linux 中的 mmap 等。

于 2009-10-21T05:34:55.343 回答
0

使用boost::shared_array作为数据容器(John 建议)。并将boost::circular_buffer作为模块中的输入队列。

boost::circular_buffer< const boost::shared_array<char> > input_queue_;

由于图像是共享的,因此您不应修改它们,而应在需要时制作新副本。

于 2009-10-21T17:44:07.680 回答