在每次循环迭代中分配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;
答案 0 :(得分:3)
我永远不会在循环中做到这一点。分配内存不是一个免费的事件,一次又一次地做绝对优先于一次又一次。 你也可以不用括号分配数组,你应该没问题:
float *array = new float[size];
答案 1 :(得分:2)
除非你测试它有多大,但实际上并不知道,但如果没有理由在循环中分配它,那么就不要。分配大量内存可能会很慢,如果你做得足够,它会降低你的代码速度 对于循环内的任何事情都可以说同样的事情。如果它不需要在那里它会更快运行(如果它被取出多快(完全取决于它是什么,分配内存比其他东西更苛刻),但如果它使代码更好/更容易它可以是值得把它留在循环中。
答案 2 :(得分:2)
堆分配的主要性能损失是碎片,而不是分配时间,这是一个累积问题。积累更少。
有一些病理病例。如果存在大量短期分配活动“跨越”块的释放和分配(例如,在另一个线程中运行相同的例程),则可能经常推动堆管理器为大块需要新内存(因为它当前占据)。这将真正破坏您的缓存并增加您的工作集。
所以有直接命中,可以直接测量:与new
相比,delete
/ do_something()
费用是多少?如果do_something
价格昂贵,那么您的评价可能不会太高。
并且存在“堆压力”,它在大型应用程序中累积。对此的贡献难以衡量,您可能会遇到由十几个独立贡献者构建的性能砖墙,事后难以识别。
答案 3 :(得分:0)
开销取决于do_something()的“权重”。当它作用于数组时,我认为它不仅仅是一些标量操作。因此,在这种情况下,您不会通过在循环外移动分配/删除来注意任何加速。但是,在上面显示的情况下,没有理由不这样做。
答案 4 :(得分:0)
将操作移出循环可提高性能。如果iter_count
很大,外部分配将更快。
new()
运算符可能(但不总是!)导致操作系统调用以获得更多内存,这是昂贵的(相对而言)。同样,delete()
调用可能会释放内存(但并不总是!),从而导致操作系统调用。
在所有情况下,请确保do_something()
不对未初始化的内存内容做出任何假设,并且可以包含随机数据。