避免异常java.lang.OutOfMemoryError而不增加堆空间?

时间:2015-10-26 20:40:52

标签: scala

我遇到了Java堆空间的问题,我在其中尝试对一个数组的连续元素进行分组,以便创建用于计算其转置的矩阵。我在数组中有很多值(26726400),我尝试使用大小为29的桶。但是当我测试下面的代码时,我得到异常java.lang.OutOfMemoryError: Java heap space

val arr = new Array[Int](256 * 3600 * 29)
    arr: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
scala> arr.grouped(29).toArray
java.lang.OutOfMemoryError: Java heap space

我的目的是转置矩阵。如果我运行sbt -mem 2048,这段代码可以正常工作,但这是另一种在不增加堆空间的情况下完成此任务的方法吗?

2 个答案:

答案 0 :(得分:1)

这可能不会节省太多内存,但它肯定比grouped更有效,后者在内部缓冲区之间进行了几次复制。

scala> val arr = new Array[Int](256 * 3600 * 29)
arr: Array[Int] = Array(0, 0, 0,...

scala> Array.tabulate(256 * 3600, 29)((i,j) => arr(i * 29 + j))
res0: Array[Array[Int]] = Array(Array(0, 0, 0,...

我的科学试验明显加快了。

您还可以使用1-dim制表,分配Array.ofDim(29)Array.copy

答案 1 :(得分:0)

嗯,在具有> 1Gb RAM的机器上的JVM实例的默认内存是RAM / 4。因此,为您的计算机添加更多内存,您不必将该参数传递给sbt。

开玩笑说,这里至少有3份数据副本。首先是原始bricks实例,然后是arr操作的结果,然后是grouped调用的结果。它甚至可能更多,我不确定隐式转换为toArray,这是调用ArrayOps方法所必需的(实际上它没有在grouped类上定义)

根据您的数据大小和类型,一个副本需要大约101Mb的内存,不包括与存储相关的任何开销。要解决此问题,请减少所制作的副本数量。例如,我真的不明白为什么你需要最后一次Array电话。

作为旁注,如果它不是作业,请考虑使用一些现有的库进行矩阵操作,例如jBLAS。