我有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替换那些浮动[] []时测试性能,但性能非常差。
所以,还有两种方法可以减少内存消耗: 1)为float [] []数组写包装器以保存“零”元素(有很多“空”行和列) 2)远离“2的力量”
这两种方式都需要相当多的编码/重构,所以当我想“成为或不成为”时 - 你可能对这个问题有更好的线索,伙计们?
谢谢!
答案 0 :(得分:1)
FFT需要一个复杂的数组,它的大小是实际数据数组的两倍,即使您从输入端的实数数组转换回最后的数字数组也是如此。这可能占内存使用量大于预期的2倍。
稀疏数组不适用于FFT,因为FFT中的中间步骤几乎总是填满整个复数数组。
许多现代高性能FFT库,例如基于FFTW的FFT库,可以非常有效地处理除了2次幂之外的FFT长度(任何长度都只是小素数的乘积,可以相当于FFT)有效率的)。这可以为许多尺寸节省大量的2D填充。
答案 1 :(得分:0)
经过更详细的调查 - 似乎JVM正在使用“UnlockEperimentalFeatures”和“使用GC1”标志启动。结果 - 有相当多的NOT垃圾收集“无法访问”BufferedImage栅格(其中包含byte []数组)。从“YourKit”priofiler调用GC时 - 那些从堆中删除的对象(这对我来说当然不可接受,因为我原以为JVM会自己管理堆)。
我要感谢所有花时间帮助我的人。 特别感谢Jim Garrison(看起来我只是推迟了内存需求一段时间去除了上面提到的标志,但是当更多阵列出现时 - 购买更多内存将是避免性能损失的最简单方法。