在循环内部分配内存vs外部循环
在循环的每次迭代中分配堆内存的大块是否会有明显的性能损失?当然,我在每次迭代结束时都会释放它。在循环内部分配内存vs外部循环
另一种方法是在进入循环之前分配一次,在所有迭代中重复使用它,并最终在退出循环后释放它。请参阅下面的代码。
// 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;
- 即使分配是固定的时间,你也有TxN而不是T.另外,如果你有任何内存块初始化(即使它只是设置为零),你反复地重复你的缓存。
堆分配的主要性能影响是碎片化,而不是分配时间,这是一个累积性问题。收集更少。
有一些病理性病例。如果有大量的短期分配活动“跨越”大块的释放和分配(例如,在另一个线程中运行相同的例程),那么您可能经常推动堆管理器为大块需要新内存(因为它现在是占据)。这将真正分解您的缓存并增加您的工作集。
所以这是直接命中,可直接测量:多少钱new
/delete
成本相比do_something()
?如果do_something
价格昂贵,则可能衡量不多。
在大型应用程序中积累了“堆压力”。对此的贡献很难衡量,你可能会遇到由十几个独立贡献者构建的性能砖墙,事后很难识别。
除非你测试它有多大,否则实际上不知道,但如果没有理由在循环内部分配它,则不需要。分配大量内存可能会很慢,如果你做得够多,它会减慢你的代码。
同样的事情可以说是循环内的任何东西。如果它不需要在那里,它会运行得更快,如果它被取出(快多快完全取决于它是什么,分配内存比其他东西更苛刻),但如果它使代码更好/更容易,它可以值得让它留在循环中。
开销取决于do_something()的“权重”。当它作用于一个数组时,我认为这比一些标量操作要多一点。所以在这种情况下,您不会通过在循环外部移动分配/删除来注意到任何加速。但是,在上面所示的情况下,没有理由不这样做。
我永远不会在循环中做它。分配内存不是免费事件,并且一次执行一次是肯定是一遍又一遍地重复执行。 您也可以只分配阵列没有括号,你应该罚款:
float *array = new float[size];
移动操作移出循环可以提高性能。如果iter_count
较大,则外部分配将更快。
new()
运算符潜在地(但并非总是)会导致操作系统调用获取更多内存,这相对昂贵(相对而言)。同样,delete()
调用也可能会释放内存(但并非总是如此!),从而也会导致操作系统调用。
在所有情况下,确保do_something()
不会对其未初始化的内存内容做任何假设,并且可能包含随机数据。
是的,Aamir应该只是进行测试。他已经写了上面的测试代码。无需推测 - 只需尝试一下。科学! – 2010-08-05 05:53:18