OpenCV中的C ++内存计数

时间:2014-12-20 08:34:22

标签: c++ multithreading opencv memory-management

我有一个用OpenCV编写的应用程序。它由两个执行OpenCV功能的线程组成。如何确定每个线程生成多少内存?

我使用libdispatch,Grand Central Dispatch设计模式。它处于一个可以同时运行多个任务的阶段。在这种情况下我如何管理记忆?通过一些opencv进程和足够的并发任务,我可以轻松达到我的RAM上限。如何管理?

C ++可以采用哪些策略?

如果每个线程都有内存限制,那怎么办呢?

此致

丹尼尔

1 个答案:

答案 0 :(得分:0)

我不熟悉您正在使用的调度库/模式,但我已快速浏览了它的目标。我在图像处理/视频处理领域做了大量的工作,所以希望我的答案不是一个完全没用的文本墙;)

我怀疑你是否将整个图像缓冲区触发到不同的线程以对它们执行相同的处理。如果是这种情况,那么您很快就会达到RAM限制。如果一个任务(线程)在其内部函数中使用了N个图像缓冲区,并且你的RAM是M,那么你可能会在M / N任务(线程)上开始用尽。如果是这种情况,那么您可能需要尝试将相关的图像块发送到线程(请参阅下面的使用依赖图进行处理的提示)。

您还应该考虑特定算法中的性能是内存绑定而不是CPU绑定的可能性。因此,即使您有额外的内核,也可能毫无意义地触发更多线程,也许在这种情况下,您最好关注像SSE / MMX这样的CPU SIMD。

首先介绍,询问(内存分配器)稍后问题

使用满足并发环境和特定内存要求的手动内存分配器可以对性能产生重大影响。但是,它们不太可能减少您使用的内存量,除非您正在使用许多小对象,在分配和回收它们时,您可以在内存布局方面做得比默认的malloc更好/免费实施。当您使用图像处理算法时,后者不太可能。您通常会在堆上分配大量的图像缓冲区,而不是许多小型结构。

我会在答案结尾处添加一些关于在哪里开始阅读滚动自己的分配器的提示,但总的来说,我的建议是首先分析并找出内存的使用位置。编写完代码后,您可能会对它已经进入的位置有一个很好的预感,但如果没有像valgrind's massif这样的工具(复杂的野兽)可能会有很大的帮助。

在对代码进行概要分析后,弄清楚如何减少内存使用量。你可以在这里做很多很多事情,这取决于使用内存的方式。例如:

  • 在您完成任务后,立即释放您不需要的任何记忆。 RAII在这里可以派上用场。
  • 除非你需要,否则不要复制内存。
  • 在适当的情况下在线程和进程之间共享内存。这将比使用不可变/复制数据更困难,因为您必须同步读/写访问权限,但根据您的问题情况,它可能会产生很大的不同。
  • 如果您正在使用内存缓存,并且由于性能原因而不想将数据缓存到磁盘,那么请考虑使用内存中压缩(例如,压缩某些缓存)&#例如,39; s落在你最近最少使用的缓存的底部。
  • 不是加载整个数据集,而是让每个方法都在整个数据集上运行,看看你是否可以对其进行整理并仅对其中的一部分进行操作。在处理大型数据集时,这尤其重要。
  • 看看您是否可以使用较低的分辨率或准确度,例如四分之一大小而不是全尺寸图像,或32位浮点数而不是64位浮点数(甚至是16位浮点数的自定义库),或者一次只使用一个图像数据通道(只是红色,或者只是蓝色,或者只是绿色,或灰度而不是RGB)。

当您正在使用OpenCV时,我猜测您正在进行图像处理或视频处理。这些很容易吞噬大量的内存。根据我的经验,初始R& D实现通常在将一个方法传递给下一个方法之前处理整个图像缓冲区。这经常导致使用多个完整图像缓冲器,这在存储器消耗方面非常昂贵。减少使用任何临时缓冲区可能是一个很大的胜利。

另一种缓解这种情况的方法是看看你是否可以找出数据依赖性(例如,通过查看低通滤波器所需的ROI),然后处理较小的图像块并再次连接它们稍后,尽可能避免临时重复缓冲区。以这种方式减少内存占用可能是一个巨大的胜利,因为您通常也会减少缓存未命中的可能性。这些方法通常会使实现变得非常复杂,除非您有一个已经支持它的基于图形的框架,否则在用尽其他选项之前,您可能不应该尝试这种方法。英特尔拥有许多与优化线程图像处理应用程序相关的优秀资源。

内存分配器提示

如果您仍然认为使用内存分配器会很有用,请参考以下提示。

例如,在Linux上,您可以使用

  • malloc hooks
  • 只是在主编译单元(main.cpp)中覆盖它们,或者是静态链接的库,或者是LD_PRELOAD的共享库。

有几种优秀的malloc /免费替代品,你可以研究想法,例如

如果您正在处理特定的C ++对象,则可以覆盖其newdelete运算符。例如,请参阅this link

最后,如果我确实设法在使用内存的地方猜错了,而事实上你确实有大量的小对象,那么在网上搜索小内存分配器'。 Alexander Alexandrescu写了几篇关于此的文章,例如: herehere