3

在每次循环迭代中分配 LARGE 堆内存块是否存在明显的性能损失?当然,我在每次迭代结束时释放它。

另一种方法是在进入循环之前分配一次,在所有迭代中重复使用它,并最终在退出循环后释放它。请参阅下面的代码。

// allocation inside loop
for(int i = 0; i < iter_count; i++) {
    float *array = new float[size]();
    do_something(array);
    delete []array;
}

// allocation outside loop
float *array = new float[size]();
for(int i = 0; i < iter_count; i++) {
    do_something(array);
}
delete []array;
4

5 回答 5

3

我永远不会在循环内这样做。分配内存不是一个免费的事件,做一次肯定比一遍又一遍地做更好。你也可以只分配没有括号的数组,你应该没问题:

float *array = new float[size];
于 2010-08-05T05:53:07.500 回答
2

除非您对其进行测试,否则永远不会真正知道它的影响有多大,但是如果没有理由在循环内分配它,则不要这样做。分配大量内存可能会很慢,如果你做得足够多,它会减慢你的代码。
对于循环内的任何内容都可以说同样的事情。如果它不需要在那里,如果它被取出它会运行得更快(速度快多少完全取决于它是什么并且分配内存比其他东西要求更高),但如果它使代码更好/更容易它可以是值得将其留在循环中。

于 2010-08-05T05:39:44.823 回答
2
  • 即使分配是恒定的时间,您也有 TxN 而不是 T。此外,如果您对块进行了任何内存初始化(即使它只是设置为零),您也会反复破坏您的缓存。
  • 堆分配对性能的主要影响是碎片,而不是分配时间,这是一个累积问题。少积累。

  • 有一些病理病例。如果有很多“跨越”块的释放和分配的短期分配活动(例如在另一个线程中运行相同的例程),您可能会经常推动堆管理器为大块需要新内存(因为它当前是占据)。这将真正分割您的缓存并增加您的工作集。

所以有直接的打击,可以直接衡量:与new/delete成本相比是do_something()多少?如果do_something很贵,你可能不会测量太多。

还有在大型应用程序中累积的“堆压力”。对此的贡献很难衡量,您可能会遇到由十几个独立贡献者构建的性能砖墙,事后很难识别。

于 2010-08-05T06:42:07.813 回答
0

开销取决于 do_something() 的“权重”。当它作用于数组时,我想它不仅仅是一些标量操作。因此,在这种情况下,您不会注意到通过将分配/删除移出循环来获得任何加速。但是,在上面显示的情况下,几乎没有理由不这样做。

于 2010-08-05T05:43:37.680 回答
0

将操作移出循环可以提高性能。iter_count特别是如果很大,外部分配会更快。

运算符可能(new()但并非总是如此!)导致操作系统调用获得更多内存,这很昂贵(相对而言)。同样,该delete()调用也可能(但并非总是!)释放内存,从而导致操作系统调用。

在所有情况下,请确保do_something()不对未初始化的内存内容做出任何假设,并且可以包含随机数据。

于 2010-08-05T05:54:55.047 回答