我想知道如何优化openCV中的数据结构(特别是mat类型),以便能够利用操作系统内置的内存/虚拟内存管理。为了全面了解情况,请阅读Q&A here - 但简单来说,我的问题可以概括为:我有一个大的mat集合,需要任意快速地访问,但全部数据的总量远超过可用的RAM数量。与其构建自己的LRU缓存和占用大量内存且效率低下的“页”寻址策略来访问它,我宁愿让操作系统为我完成这项工作。我认为我理解了这些概念,但当涉及实际实现时,我无从下手。
这是一个通用的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视为巨大虚拟地址空间的缓存。mmap
ing大文件而不是进行匿名分配来分配内存,则非常类似于所得到的内容。