【问题标题】:For loop or no loop? (dataset is small and not subject to change)有循环还是无循环? (数据集很小,不会改变)
【发布时间】:2016-11-30 21:33:23
【问题描述】:

假设我有一个已知大小的小矩阵,其大小在软件的生命周期内不太可能发生变化。如果我需要检查每个矩阵元素,使用循环或手动索引到每个矩阵位置会更有效吗?

例如,假设我有一个由 3 个窗口组成的系统,每个窗口有 2 个窗格。我需要跟踪每个窗格的状态。在我的系统中,只有 3 个窗口,每个窗口 2 个窗格。

static const int NUMBER_OF_WINDOWS = 3;
static const int NUMBER_OF_PANES = 2;

static const int WINDOW_LEFT = 0;
static const int WINDOW_MIDDLE = 1;
static const int WINDOW_RIGHT = 2;

static const int PANE_TOP = 0;
static const int PANE_BOTTOM = 1;

paneState windowPanes[NUMBER_OF_WINDOWS][NUMBER_OF_PANES];

这些访问方法中哪一种更有效?

循环版本:

for (int ii=0; ii<NUMBER_OF_WINDOWS; ii++)
{
  for (int jj=0; jj<NUMBER_OF_PANES; jj++)
  {
    doSomething(windowPanes[ii][jj];
  }
}

对比

手动访问版本:

doSomething(windowPanes[WINDOW_LEFT][PANE_TOP]);
doSomething(windowPanes[WINDOW_MIDDLE][PANE_TOP]);
doSomething(windowPanes[WINDOW_RIGHT][PANE_TOP]);

doSomething(windowPanes[WINDOW_LEFT][PANE_BOTTOM]);
doSomething(windowPanes[WINDOW_MIDDLE][PANE_BOTTOM]);
doSomething(windowPanes[WINDOW_RIGHT][PANE_BOTTOM]);

循环代码是否会生成分支指令,这些指令是否会比手动访问时生成的指令成本更高?

【问题讨论】:

  • 最好使用定义 (#define NUMBER_OF_WINDOWS 3) 而不是常量,因为编译器更明显地根据我的回答优化 for 循环。
  • 如果你真的想知道,用-S 编译并查看程序集。和/或分析两组代码。根据doSomething 中的代码,编译器可以做出很多不同的选择。
  • “数据集......不会更改”。直到它发生。

标签: c++ c performance


【解决方案1】:

经典的效率与组织。 for 循环更易于人类阅读,手动方式更易于机器阅读。

我建议您使用循环。因为编译器,如果启用了优化,当它看到上限是常量时,它实际上会为你生成手动代码。这样您就可以两全其美。

【讨论】:

    【解决方案2】:

    首先:你的函数doSomething有多复杂?如果是(很可能是这样),那么您不会注意到任何差异。

    一般来说,顺序调用你的函数会比循环稍微有效一些。但是再一次,收益将是微乎其微的,不值得讨论。

    请记住,优化编译器执行loop unrolling。这本质上是生成代码,将循环旋转更少的次数,同时在每次旋转中做更多的工作(它们将依次调用你的函数 2-4 次)。当旋转次数较少且固定时,编译器可以很容易地完全消除循环。

    从清晰和易于修改的角度看待您的代码。在许多情况下,编译器会做很多与性能相关的有用技巧。

    【讨论】:

      【解决方案3】:

      你可以线性化你的多维数组

      paneState windowPanes[NUMBER_OF_WINDOWS * NUMBER_OF_PANES];
      
      and then
      
      for (auto& pane : windowPanes) {
          doSomething(pane);
      }
      

      如果编译器不优化它可以避免额外的循环。

      【讨论】:

        猜你喜欢
        • 2018-06-26
        • 1970-01-01
        • 1970-01-01
        • 2022-12-18
        • 1970-01-01
        • 2017-06-21
        • 2010-10-30
        • 2020-10-10
        • 1970-01-01
        相关资源
        最近更新 更多