【问题标题】:Optimising data-structures so that they take advantage of virtual memory优化数据结构以利用虚拟内存
【发布时间】:2016-08-10 23:13:57
【问题描述】:

我想知道如何优化 openCV 中的数据结构(特别是 mat 类型),以便我能够利用内置于内存/虚拟内存管理中的操作系统。

有关完整的上下文,请阅读 Q 和 A here - 但否则情况可以总结为我有大量的垫子* 我需要访问 任意快速。主要的复杂性是全部数据量远高于可用 RAM 量。

(*从概念上讲,数据是递归定义的 3D 数组的 3D 数组,但我们不要因为这种混淆而搅浑水!)

与其构建我自己的 LRU 缓存和大量 RAM 且效率低下的“页面”寻址策略来访问它,我宁愿让操作系统为我做这件事。

我想我明白了这些概念,但是当谈到实际的实现时,我只是在摆弄拇指:

  • 这是一个通用的 C++ 考虑因素,还是我需要在 openCV 级别解决的问题?

  • 是否像使数据的粒度接近(但不超过)4KB 一样简单? (有关 4KB 动机,请参阅解决方案 here

  • 实际如何在磁盘上保存、访问和表示垫子? (这就是memory-mapping的参与方式吗?)

【问题讨论】:

  • 如果您可以管理访问模式,例如从头到尾读取 1 mb 的线性地址空间,操作系统将非常擅长预测您接下来要阅读的内容,并提前为您阅读.但实际上,过了某个时间点,您将受到磁盘 io 的限制(除非您正在使用疯狂的快速硬盘存储);因此,您在该限制下的目标是避免多次阅读内容(好吧,稍后停止阅读以避免颠簸)。基本上,尝试反击任意。那里的任何改进都可能支配您可以做的任何其他事情。
  • @Yakk,“避免多次阅读内容”:这就是 LRU/LFU 缓存的工作原理——据我所知,这种功能隐含在内存管理背后的算法中。跨度>

标签: c++ performance opencv caching memory-management


【解决方案1】:

这是一个通用的 C++ 考虑因素,还是我需要在 openCV 级别解决的问题?

您只需分配和使用大量内存。 分页/虚拟内存的全部意义在于它是完全透明的。一切都变得非常缓慢,但继续工作。在交换空间 + RAM 用完之前,您不会得到 ENOMEM

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

是否像使数据的粒度接近(但不超过)4KB 一样简单? (有关 4KB 的动机,请参见此处的解决方案)

如果您有指向其他数据的指针,请确保将它们放在一起。您希望所有小的“热”数据仅位于体面的 OS LRU 算法不会分页的几页中。

如果您将热数据与冷数据混合在一起,它很容易被分页并导致额外的页面文件往返,甚至可能发生最终数据的缓存未命中。

就像 Yakk 所说,顺序访问模式会做得更好,因为磁盘 I/O 在多块读取方面做得更好。 (即使 SSD 具有更大的块也有更好的吞吐量)。这也允许预取,它允许一个 I/O 请求在前一个数据到达之前开始。最大化 I/O 吞吐量需要流水线请求。

尽可能设计您的算法以进行顺序访问。这对所有级别的内存都是有利的,从分页一直到 L1 缓存。顺序访问甚至可以使用向量寄存器实现自动向量化。

Cache blocking (aka loop tiling) 技术也适用于页面未命中。谷歌了解详细信息,但主要思想是在数据子集上执行算法的所有步骤,而不是在每个步骤中接触所有数据。然后每条数据总共只需加载一次缓存,而不是算法的每一步加载一次。

将 DRAM 视为巨大虚拟地址空间的缓存。


实际如何在磁盘上保存、访问和表示垫子? (这就是内存映射的方式吗?)

Swap space / the pagefile is the backing store for your process's address space。所以是的,这与您通过mmaping 分配内存而不是匿名分配的情况非常相似。

【讨论】:

    猜你喜欢
    • 2012-11-17
    • 1970-01-01
    • 2010-09-06
    • 2014-09-15
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    相关资源
    最近更新 更多