代码之家  ›  专栏  ›  技术社区  ›  Aamir

在循环内分配内存与在循环外分配内存

  •  3
  • Aamir  · 技术社区  · 16 年前

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

    // 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;
    
    5 回复  |  直到 16 年前
        1
  •  2
  •   peterchen    16 年前
    • 即使分配是常数时间,也有TxN而不是T。此外,如果您有任何块的内存初始化(即使它只是设置为零),您会重复地重击您的缓存。

    所以有一个直接的打击,它可以直接衡量:有多少 new delete 成本与 do_something() ? 如果 do_something

    在一个大型应用程序中积累了“堆压力”。这方面的贡献很难衡量,你可能会碰到一堆独立贡献者建立的性能砖墙,而这些贡献者在事后很难确定。

        2
  •  3
  •   C.J.    16 年前

    我决不会在圈内做。分配内存不是一个空闲事件,只分配一次就可以了 一定地 另外,您可以只分配不带括号的数组,这样就可以了:

    float *array = new float[size];
    
        3
  •  2
  •   cohensh    16 年前

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

        4
  •  0
  •   FFox    16 年前

    开销取决于do\u something()的“重量”。当它作用于一个数组时,我想它不仅仅是一些标量操作。因此,在这种情况下,您不会注意到将分配/删除移到循环之外会有任何加速。然而,在上述情况下,没有什么理由不这样做。

        5
  •  0
  •   Manfred    16 年前

    将操作移出循环可以提高性能。特别是如果 iter_count 它很大。

    new() 运算符(但不总是!)导致操作系统调用获得更多内存,这是昂贵的(相对而言)。同样 delete() 调用可能会释放内存(但不总是!)同时导致操作系统调用。

    在任何情况下,确保 do_something() 不做任何关于内存内容的假设它没有初始化,并且可以包含随机数据。