【问题标题】:Which is better, to define the variable inside the loop or outside, with huge loop times [closed]哪个更好,在循环内部或外部定义变量,循环时间很长[关闭]
【发布时间】:2022-01-23 00:08:35
【问题描述】:

我需要在循环中使用数组,循环时间非常巨大。

案例1:在for循环外定义数组并传递给fun2

void fun1(){
    int temp[16];
    for(int i = 0;i <times; i++)
    {
        fun2(temp);
    }       
}

void fun2(int[]& temp){
    /**  do something with temp*/
}

案例2:在fun2中定义数组:

void fun1() {
    for (int i = 0; i < times; i++)
    {
        fun2();
    }
}

void fun2() {
    int temp[16];
    /**  do something with temp */
}

fun1 会经常被调用。在这种情况下,哪个更好?

案例 2 对性能有影响吗?

【问题讨论】:

  • 检查生成的汇编代码。虽然我怀疑将它作为参数传递给函数会更有效
  • 我认为这两个版本在发布模式下都不会显着改变性能。如果有什么我希望在打开优化而不使用调试模式时,案例 #1 会稍微慢一些。
  • 如果它真的很重要,不要猜测,测量它。如果不是,那你就是在浪费时间,从功能的角度选择更有意义的一个,然后继续。
  • 现在我上面的评论与int temp[16];有关。如果您有myClass temp[16];,我的答案会有所不同,两个代码版本的行为也会有所不同。
  • 为多种目的重用变量是一种非常可靠的引入错误的方法。声明尽可能接近使用,重新考虑它是否是性能问题。 (这可能会让您感到惊讶,但第一个版本实际上比第二个版本做得更多。)

标签: c++ for-loop


【解决方案1】:

如果您要寻找一般情况的答案,答案是“视情况而定”。如果您想知道具体示例的答案,答案是第二个版本会更高效。

问问自己:

  1. 建设/销毁/再利用是否需要成本?

在您的示例中,没有(调整堆栈指针除外,这非常便宜)。但如果它是一个对象数组,或者您必须将数组初始化为特定值,情况就会改变。

  1. 如何影响参数化成本?

这非常小,但在您的第一种情况下,您传递了一个指向函数的指针。如果函数没有内联,这意味着数组只能通过该指针访问。这占用了一个可以在其他情况下使用的寄存器。第二个例子,可以通过栈指针访问数组,基本上是空闲的。

它还会对别名和转义分析产生负面影响,从而导致代码效率降低。基本上,如果编译器不能证明后面的内存读取可能不引用相同的值,则编译器必须将值写入内存而不是将它们保存在寄存器中。

  1. 哪个版本更健壮?

第二个版本确保数组的大小始终正确。另一方面,如果您传递一个其构造函数可能引发异常的对象,则在函数外部构造可能允许您在更方便的位置引发异常。这对于异常安全保证可能很重要。

  1. 提前解除分配有什么好处吗?

是的,分配和解除分配的成本很高,但提前销毁可能允许一些重用。我遇到过这样的情况,即提前释放对象允许在代码的其他部分重用内存,从而提高了 CPU 缓存的使用。

【讨论】:

    【解决方案2】:

    取决于您想要实现的目标..在这种情况下,我假设您正在寻找性能,哪种情况 2 会是更好的选择,因为函数会动态创建变量而不是尝试获取变量全局然后它的值。

    【讨论】:

      猜你喜欢
      • 2010-12-25
      • 2012-12-02
      • 1970-01-01
      • 2012-02-06
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      相关资源
      最近更新 更多