优化数据结构以利用虚拟内存

4
我想知道如何优化openCV中的数据结构(特别是mat类型),以便能够利用操作系统内置的内存/虚拟内存管理。为了全面了解情况,请阅读Q&A here - 但简单来说,我的问题可以概括为:我有一个大的mat集合,需要任意快速地访问,但全部数据的总量远超过可用的RAM数量。与其构建自己的LRU缓存和占用大量内存且效率低下的“页”寻址策略来访问它,我宁愿让操作系统为我完成这项工作。我认为我理解了这些概念,但当涉及实际实现时,我无从下手。
  • 这是一个通用的C++问题,还是我需要在openCV层面上解决?

  • 是否只需将数据的粒度接近(但不超过)4KB即可?(有关4KB动机的解决方案,请参见此处

  • mat(s)实际上如何保存、访问和表示在磁盘上?(这是否涉及内存映射?)

2
如果您可以管理访问模式,例如从开头到结尾读取1 mb的线性地址空间,操作系统将非常擅长预测您接下来想要读取什么,并提前为您读取。但实际上,在某个点之后,您将受到磁盘io的限制(除非您使用疯狂快速的硬存储);因此,在达到极限时,您的目标是避免重复读取内容(或在一段时间后停止读取以避免抖动)。基本上,试图反对任意性。在那里进行的任何改进可能会支配您所能做的任何其他事情。 - Yakk - Adam Nevraumont
@Yakk,“避免重复读取信息”:这就是LRU/LFU缓存管理的作用 - 据我所知,这种功能在内存管理算法中是隐含的。 - Lamar Latrell
1个回答

1

这是一个通用的C++问题,还是我需要在openCV层面上解决?

你只需分配并使用大量内存。 页面/虚拟内存的整个意义在于它完全透明。所有东西都变得极其缓慢,但仍然可以工作。直到你的交换空间+ RAM耗尽才会出现ENOMEM

在正常的Linux系统上,你的普通交换分区应该非常小(小于1GB),所以你可能需要dd一个交换文件,并在上面mkswap/swapon。确保交换文件只有root才具有读写权限。显然,每个主要的操作系统都有自己的程序。

是否简单地将数据的粒度接近(但不超过)4KB就可以了?(请参见此处的4KB动机解决方案)

如果你有指向其他数据的指针,请确保将它们放在一起。你希望所有小的“热”数据只存在于少数页面中,而一个体面的OS LRU算法不会将它们换出。

如果您的热数据和冷数据混合在一起,很容易被分页并导致额外的页面文件往返,甚至在最终数据的高速缓存未命中之前。正如Yakk所说,顺序访问模式会更好,因为磁盘I/O在多块读取时表现更佳(即使是SSD也具有更大的吞吐量)。这还允许预取,使得一个I/O请求可以在上一个请求的数据到达之前开始。最大化I/O吞吐量需要流水线请求。尽可能设计算法以进行顺序访问是有利的,从分页到L1缓存的所有内存级别都是如此。顺序访问甚至可以通过向量寄存器实现自动向量化。缓存块(又称循环平铺)技术也适用于页面丢失。搜索Google以获取详细信息,但主要思想是在数据的子集上执行算法的所有步骤,而不是在每个步骤中触及所有数据。然后,每个数据只需总共加载到缓存一次,而不是在算法的每个步骤中加载一次。将DRAM视为巨大虚拟地址空间的缓存。
“垫子实际上会如何保存、访问和在磁盘上表示?(这是否涉及内存映射?)”。交换空间/页面文件是进程地址空间的后备存储。因此,如果您通过mmaping大文件而不是进行匿名分配来分配内存,则非常类似于所得到的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接