我从传感器(相机)获取数据并将数据写入二进制文件。问题是它需要占用大量磁盘空间。 所以,我使用了boost(zlib)的压缩,空间减少了很多!问题是压缩过程很慢并且缺少大量数据。
所以,我想实现两个线程,一个从相机获取数据并将数据写入缓冲区。第二个线程将获取缓冲区的前端数据并将其写入二进制文件。在这种情况下,所有数据都将存在。
如何实现此缓冲区?它需要动态扩展和pop_front。我应该使用std :: deque,还是已经存在更好的东西?
答案 0 :(得分:0)
首先,您必须考虑这四种速率(或速度):
如果 SC 小于 SP ,则表示您遇到了麻烦。这意味着您无法实时压缩从传感器收集的所有数据。这意味着你最终会耗尽缓冲存储器。您必须找到更快的压缩算法,或者将更多CPU内核专用于压缩。
如果 SW 小于 SP 次 RC (压缩后传感器数据的大小),则再次遇到麻烦。这意味着你不能像生成和压缩它们那样快地写出输出数据,而且无论你有多少,你最终都会耗尽缓冲存储器。您可以通过采用更好的写入策略或文件系统来获得一些速度,但 SW 的真正好处来自更好的磁盘系统(RAID,SSD,更好的硬件等)
现在,如果速度一切正常,您可以使用以下架构来读取,压缩和写入数据:
您将拥有三个线程(或两个,稍后描述),每个线程执行管道的一部分。您还将拥有两个线程安全队列,一个用于从管道的每个阶段到下一个阶段的通信。
假设两个队列名为Q1
和Q2
,则线程的高级操作将如下所示:
K
字节的传感器数据K
个字节作为一个整数放在Q1
。Q1
上有某事。K
弹出一个数据缓冲区(可能是Q1
个字节)。Q2
。Q2
上有某事。Q2
弹出一个数据缓冲区。工作中CPU占用最多的部分是在第二个线程中,另外两个可能不会消耗太多CPU时间,因此可能可以共享一个CPU核心。这意味着上述策略可以在两个核上运行。但是,如果工作负载很轻,或者需要许多核心,它也可以在单个核心上运行。这完全取决于我所描述的四种费率。
使用异步写入(例如,Windows上的IOCP或Linux上的epoll),您可以完全删除第三个线程和第二个队列。然后你的第二个线程需要执行这样的事情:
Q1
上有某事。K
弹出一个数据缓冲区(可能是Q1
个字节)。还有四个值得一提的问题:
K
,以便与分配缓冲区相关的各种(通常是常量时间)活动所需的时间,将其推入并从线程安全队列中弹出,开始压缩运行并且在执行实际工作(读取传感器数据,压缩字节和写入磁盘)时,向文件发出写入请求变得可以忽略不计。这通常意味着K
需要尽可能大。但是如果K
非常大(许多兆字节或几百兆字节),那么如果您的应用程序崩溃,您将丢失大量数据。您需要在性能和数据丢失风险之间找到平衡点。我建议(在不知道您的具体需求和约束的情况下)K
的值介于10KiB到1MiB之间。
如果您对并发/并行编程有一定的知识和经验,那么实现一个线程安全的队列很容易,但如果不这样做,则很容易并且容易出错。找到好的例子和实现应该不难。正常的std::deque
或std::list
或std::
任何东西本身都无法使用,但可以用作编写线程安全队列的良好基础。
请注意,您正在排队数据缓冲区,而不是单个数字或字节。如果您通过此管道一次传递一个数字,那将非常缓慢且浪费。
某些压缩算法受限于每次调用可以消耗多少数据,或者您必须将每次调用的输出同步到压缩例程,稍后再调用一次解压缩例程。这些可能会影响K
的选择,以及您编写输出文件的方式。您可能必须添加一些元数据,以便以后能够实际解压缩和读取数据。