【问题标题】:Optimizing reiterated array allocation优化重复数组分配
【发布时间】:2014-05-19 20:03:21
【问题描述】:

考虑这些类似的代码:

for (int iteration = 0; iteration<a_lot; iteration++) {
    int[] re = new int[large];
    for (int i = 0; i<large; i++)
        re[i] = computeValue();
    ...
}

int[] re = new int[large];
for (int iteration = 0; iteration<a_lot; iteration++) {
    for (int i = 0; i<large; i++)
        re[i] = computeValue();
    ...
}

在第一个示例中,我们在每次迭代中为数组重新分配新空间,并让垃圾收集器在前一次迭代中释放数组空间,而在第二个示例中,我们重用相同的数组。 我可以想象,在某些情况下,第一个算法会导致(或导致)StackOverflowException,而第二个算法的缺点是数组在迭代之间永远不会被垃圾收集,即使在某个时间点之后可能会出现这种情况数组不再使用的迭代。

在什么情况下使用哪种算法更好?

【问题讨论】:

  • 显然第二个数组最终会被垃圾回收。除非您将其存储在类级别,否则它会在某些时候超出方法范围。
  • 这个问题/答案对您有帮助吗? stackoverflow.com/questions/377763/…
  • @Kon 这是真的,请参阅编辑。 "数组永远不会被垃圾回收在迭代之间"
  • @RaulGuiu 我不认为这是同一个问题。我的问题是关于数组分配,而不是变量声明及其范围。

标签: java arrays optimization memory-management garbage-collection


【解决方案1】:

首先,您认为为什么会收到 StackOverflowException?数组将存储在堆上(引用将在堆栈上)。 其次,GC 足够聪明,可以在这两种情况下清理内存。实际上只要不需要引用,Garbage Collector 就可以调用内存(它可以调用内存,同时还在方法中。)

【讨论】:

  • GC 不会在不再需要引用的那一刻发生; GC 是清理所有不需要的对象的批处理过程。在第二个示例中,每次迭代都需要引用,所以我认为不会清理内存。在该示例中,引用保持不变,但包含的所有整数都会改变。
【解决方案2】:

除非您的数组非常庞大以至于必须在每次迭代时释放它,否则我认为每次都重新分配它没有任何好处。

【讨论】:

  • 根据一些超参数,我有时会遇到堆空间问题。我试图弄清楚是否应该将程序中的程序更改为我的第一个示例,以减少发生此类错误的机会。这是我必须释放数组的情况吗?
  • @TimKuipers 很难说,你的数组 那么 大吗?你能给我们看一个你的相关代码的例子吗?还有你在启动你的应用程序时使用了哪些参数?
  • 我正在实现卷积神经网络。很难向您展示相关代码。不是数组有那么大,而是我有很多。对于每个图像,对于每个神经元,在每一层中,我都有双精度的 3 维数组。整个网络的每次迭代都会重新计算与每个图像的每一层的(中间)输出相对应的 3 维数组。我想知道为(中间)输出重新分配数组是否会更好 - 而不是网络中神经元之间连接权重的数组。
  • 如果您重新分配,您的应用程序是否工作得更好(堆空间问题更少)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多