5

我有 Java 应用程序,它集中使用 2D 浮点数组(float[][] 数组),它实际上在黑色背景上保存图像。两个维度都等于(正方形)并且是 2 的幂(大多数是 256、512、1024),因此在大多数情况下,靠近边界的区域为零。

大小等于 2 的幂是为了提高性能(有一些 FFT)并降低对这些阵列的操作(如旋转等)的复杂性。最近,我在 6Gb 的机器上遇到了这个应用程序的堆不足问题。根据我的计算 - 此应用程序的内存消耗应该高达 2-3Gb,而它达到 4-5Gb(在 Windows 任务管理器中查看)。我使用了“YourKit”分析器,它表明这些浮点数组确实占用了大部分内存,但是,这些浮点数组的总粗略大小应该是 1.3Gb(嗯,我知道由 JVM 来决定如何存储数据,但是我没想到内存消耗会相差 2-3 倍)。

我试图使用 Snappy 压缩器即时压缩/解压缩数据(内存消耗下降到 3.5Gb),但性能下降了好几次,这不是很可接受。另外,我在用 BufferedImage 替换那些 floats[][] 时测试了性能,但性能很差。

所以,剩下的 2 种方法对我来说可以减少内存消耗:1)为 float[][] 数组编写包装器以保存“零”元素(有很多“空”行和列)2 ) 远离“2 的幂”

这两种方式都需要大量的编码/重构,所以当我在想“成为或不成为”的时候——也许你对这个问题有更好的线索,伙计们?

谢谢!

4

2 回答 2

1

FFT 需要一个复数数组,它是实际数据数组大小的两倍,即使您在输入处从实数数组转换并在最后转换回幅度数组也是如此。这可能占内存使用量超出预期的 2 倍。

稀疏数组不适用于 FFT,因为 FFT 中的中间步骤几乎总是会填充整个复数数组。

许多现代高性能 FFT 库,例如基于 FFTW 的库,可以非常有效地处理 FFT 长度,而不仅仅是 2 的幂(任何长度只是小素数的乘积都可以非常有效地进行 FFT)。这可以为许多尺寸节省大量 2D 填充。

于 2013-11-07T21:11:12.257 回答
0

经过更详细的调查 - 似乎 JVM 启动时带有“UnlockEperimentalFeatures”和“use GC1”标志。结果 - 有很多非垃圾收集的“无法访问”的 BufferedImage 栅格(其中包含 byte[] 数组)。从“YourKit”priofiler 调用 GC 时 - 从堆中删除的那些对象(这对我来说当然是不可接受的方式,因为我期望 JVM 会自己管理堆)。

我要感谢所有花时间帮助我的人。特别感谢 Jim Garrison(看起来我只是将内存需求推迟了一段时间,删除了上面提到的标志,但是当更多的阵列开始发挥作用时——购买更多的内存将是避免性能损失的最简单方法。

于 2013-11-09T09:42:32.453 回答