2

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

该程序首先索引我提供的大量文本文件。这工作正常。

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

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

我做过的事情包括:

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

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

谢谢,B。

4

4 回答 4

2

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

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

于 2010-03-17T05:02:26.423 回答
2

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

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

如果您的问题不是那么简单,那么您可以查看优化。用基元替换对象等等。这可能是一种选择。根据您发布的内容,我真的不能说。

然而,最终你会遇到一个十字路口,你必须在虚拟化分区之间做出选择。

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

分区是将您的数据拆分到多个服务器(无论是真实的还是虚拟的)。例如,如果您在 NASDAQ 跟踪股票交易,您可以在 server1 上放置以“A”开头的股票代码,在 server2 上放置以“B”开头的股票代码,等等。您需要找到一种合理的方法来分割您的数据,以便减少或者消除对交叉通信的需要,因为交叉通信限制了您的可扩展性。

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

  • 上午 x 上午
  • 上午 x 新西兰
  • 新西兰 x 上午
  • 新西兰 x 新西兰

这只是一个想法。再一次,在不知道细节的情况下很难评论。

于 2010-03-17T05:06:11.327 回答
1

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

于 2010-03-17T05:04:05.943 回答
0

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

于 2010-03-17T05:00:53.407 回答