好的,所以我正在编写一个程序,不幸的是需要使用巨大的数据结构来完成其工作,但它在初始化期间因“内存不足错误”而失败。虽然我完全理解这意味着什么以及为什么这是一个问题,但我很难克服它,因为我的程序需要使用这个大型结构,并且我不知道任何其他方式来存储它。

该程序首先索引我提供的大量文本文件。这很好用。

然后它使用这个索引来初始化一个大的二维数组。该数组将有 n² 个条目,其中“n”是文本语料库中唯一单词的数量。对于相对较小的块,我正在(大约 60 个文件)上进行测试,它需要创建大约 30,000x30,000 个条目。一旦我在完整的预期语料库上运行它,它可能会更大。

在索引之后,在初始化数据结构(稍后处理)时,它每次都会失败。

我做过的事情包括:

  • 修改我的代码以使用原语 int[] 代替 TreeMap
  • 消除冗余结构等...
  • 另外,我已经运行了该程序-Xmx2g 最大化我分配的内存

我相当有信心这不会是一个简单的代码行解决方案,但很可能需要一种非常新的方法。我正在寻找这种方法是什么,有什么想法吗?

谢谢,B。

有帮助吗?

解决方案

听起来(对您使用数组的用途做出一些假设)大多数条目将为 0。如果是这样,您可以考虑使用 稀疏矩阵 表示。

如果你真的 那么多条目(您当前的数组位于某处 已经超过 3 GB, ,即使假设没有开销),那么您将不得不使用某种磁盘存储,或延迟加载/卸载系统。

其他提示

内存不足问题的原因有多种。

首先,最简单的情况是您只需要更多堆。当您的程序可以在 2G 下正常运行时,您正在使用 512M 最大堆。增加是与 -Xmx2048m 作为 JVM 选项,你就可以了。另请注意,64 位 VM 使用的内存最多是 32 位 VM 的两倍,具体取决于数据的构成。

如果您的问题不是那么简单,那么您可以考虑优化。用原语替换对象等等。这可能是一个选择。根据您发布的内容,我真的无法说。

然而最终你来到了一个十字路口,你必须在两者之间做出选择 虚拟化划分.

虚拟化 在这种情况下,仅仅意味着某种形式的假装内存比实际多。操作系统将其与虚拟地址空间结合使用,并使用硬盘空间作为额外内存。这可能意味着一次仅将一些数据结构保留在内存中,并将其余数据结构持久保存到辅助存储(例如文件或数据库)。

分区 将您的数据分散到多个服务器(真实的或虚拟的)。例如,如果您要跟踪纳斯达克的股票交易,您可以在服务器 1 上输入以“A”开头的股票代码,在服务器 2 上输入以“B”开头的股票代码,等等。您需要找到一种合理的方法来分割数据,以便减少或消除交叉通信的需要,因为交叉通信限制了您的可扩展性。

如此简单的情况,如果您要存储的是 30K 单词和 30K x 30K 单词组合,您可以将其分为四个服务器:

  • A-M x A-M
  • A-M x N-Z
  • N-Z x A-M
  • N-Z x N-Z

这只是一个想法。同样,在不了解具体情况的情况下很难发表评论。

这是处理大型数据集的常见问题。您可以根据需要进行优化,但内存永远不会足够(可能),并且一旦数据集增长一点,您仍然会被熏。最具可扩展性的解决方案就是减少内存占用,处理块,并将结构保留在磁盘(数据库/文件)上。

如果您的 2D 数组中的每个值不需要完整的 32 位(整数大小),也许更小的类型(例如字节)可以解决问题?此外,您还应该为其提供尽可能多的堆空间 - 对于现代系统来说 2GB 仍然相对较小。RAM 很便宜,尤其是当您希望在内存中进行大量处理时。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top