【问题标题】:How to handle an array with size 1,000,000,000 in C++?如何在 C++ 中处理大小为 1,000,000,000 的数组?
【发布时间】:2012-03-06 17:05:42
【问题描述】:

我需要处理 3D 立方体数据。它的元素数量可以达到数十亿。我知道我无法在 Windows 上分配那么多内存。所以我正在考虑使用进程内数据库进行基于磁盘的操作。有没有更好的方法来做到这一点?也许有什么提升?

更新:我最终将不得不提供带有绘图的浏览功能。

Update2:以下文章似乎是使用内存映射文件的一个很好的解决方案。我会尝试并再次更新。 http://www.codeproject.com/Articles/26275/Using-memory-mapped-files-to-conserve-physical-mem

【问题讨论】:

  • 嗯,Win7 Pro 最高支持 192GB,我觉得不止几个 :)
  • 请解释您要如何处理您的数据。有了这么多元素,您真的想仔细考虑您要完成的工作。您将运行的算法将确定适当的数据结构。例如,我想你可能实际上在谈论一个 1000x1000x1000 的立方体,也许大多数元素都是空的。也许你想要一个八叉树。但也许需要一些完全不同的东西。我们需要更多信息。
  • @AlanBaljeu 我希望你的猜测是正确的。但立方体是具有另一个密集维度的图像。所以我需要这么大的尺寸,所有元素都同样重要。
  • @david:我们在这里谈论的是用户模式吗?如果它是 32 位进程,则绝对限制应该是(通常)2 GiB 的 RAM,而在 64 位中,由 Igor 命名的限制适用。带 PAE 的 32 位仍然具有与不带 PAE 相同的每个进程限制,但总体上支持高达 64 GiB,IIRC。
  • 查看我对这个问题的回答:stackoverflow.com/questions/9227653/… - OP 遇到了类似的问题。

标签: c++ boost


【解决方案1】:

第一步也是最基本的步骤是将数据分解成块。块的大小取决于您的需求:它可以是可以一次绘制的最小或最大块,或者可以为其构建几何图形,或者是用于压缩的最佳大小。

一旦您使用了可管理的块,就可以避免直接的内存问题。根据需要流式传输块(加载和卸载/保存)。

在加载/保存过程中,您可能希望涉及压缩和/或各种数据库。即使是像 RLE 和 SQLite(带有坐标和数据块的单个表)这样简单的东西也可以节省大量空间。更好的压缩将允许您使用更大的块大小。

根据使用情况,可以将块压缩在内存中,并且仅在修改时(或在可以修改时)短暂解压缩。如果您的数据是只读的,那么加载它们并仅在需要时解压缩将非常有帮助。

将数据分割成块还有其他好处,例如作为八叉树的一种极其简单的形式,允许几何生成(行进立方体等)在隔离的数据块上运行(简化线程),并使保存/加载过程明显更简单。

【讨论】:

  • 再一次,我的数据是具有另一个密集维度的图像。我不确定如何将数据分成块。是的,我也在考虑 SQLite。我真的希望有更好的 API。谢谢你的回答。
  • 如果您的数据是图像,自然的假设是按图像分割。这将在切片上下文中工作。如果数据依赖于它的 3D 邻居,它会稍微复杂一些。如果您可以在问题中更详细地描述数据,或者最好提供一个小样本,那将很有帮助。
  • 是的,数据依赖于它的 3D 邻居。这是高光谱图像。所以我不能真正按图像分割
  • 图像并不依赖于所有的邻居,只有少数例外。在任何情况下,您都可以获取堆栈的一个区域;通过在一堆图像中挤出一个正方形而形成的形状。谷歌地图使用类似的功能来处理流图块,有效地处理单层堆栈。根据图像的深度到宽度,该方法可能会起作用(您可能需要一个小的边距来实现 mipmapping 和其他模糊效果)。
  • 在这种情况下,它们依赖于所有邻居。
【解决方案2】:

您能否更有效地存储数据(阅读 Bentley 的“Programming Pearls”),它是稀疏数据吗?!

如果不是,内存映射文件 (MMF) 是您的朋友,它允许您将 MMF 块映射到您可以像访问任何其他内存一样访问的内存中。

使用CreateFileMappingMapViewOfFile 将块映射到您的进程中。

【讨论】:

  • 感谢您的回答。不,它一点也不稀疏。这是具有另一个密集维度的图像。你能给我一些关于如何处理MMF的参考吗?我真的希望有一个简单的库,所以我可以像数组一样使用它。
  • 我没有直接使用您的答案,但我找到了使用内存映射文件的解决方案。谢谢你给我指路。
【解决方案3】:

<windows.h> 尝试 VirtualAlloc。

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887%28v=vs.85%29.aspx

它对大型阵列非常有用,只要它们适合您的 RAM,之后 0xC0000022L 的答案可能是更好的解决方案

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多