【问题标题】:Does it change performance to use a non-int counter in a loop?在循环中使用非整数计数器会改变性能吗?
【发布时间】:2009-04-02 22:42:15
【问题描述】:

我只是好奇,在任何地方都找不到答案。通常,我们在循环中使用整数作为计数器,例如在 C/C++ 中:

for (int i=0; i<100; ++i)

但我们也可以使用短整数甚至字符。我的问题是:它会改变性能吗?它少了几个字节,因此节省的内存可以忽略不计。如果我知道计数器不会超过 100,那么如果我使用 char 会造成任何伤害,这只会让我很感兴趣。

【问题讨论】:

    标签: performance for-loop int


    【解决方案1】:

    可能使用平台的“自然”整数大小将提供最佳性能。在 C++ 中,这通常是 int。但是,差异可能很小,您不太可能发现这是性能瓶颈。

    【讨论】:

    • 它有时确实会发生。在最近的一个标题中,分析器告诉我,我们在迭代器中花费了 7% 的 CPU 用于一个无处不在的容器类。经过调查,我发现它的索引类型使用了缩写;将其更改为 int 会使该函数低于 1%。
    【解决方案2】:

    取决于架构。在 PowerPC 上,使用除 int 以外的任何内容(或任何原生字长)通常会导致巨大的性能损失——例如,不要使用 short 或 char。 Float 也即将推出。

    您应该在您的特定架构上计时,因为它会有所不同,但在我的测试用例中,使用 short 而不是 int 会降低约 20% 的速度。

    【讨论】:

      【解决方案3】:

      我无法提供引用,但我听说您经常使用 short 或 char 会产生一点性能开销。

      内存节省是不存在的,因为它是一个临时堆栈变量。它所在的内存几乎肯定已经被分配了,你可能不会通过使用更短的内存来节省任何东西,因为下一个变量可能无论如何都希望与更大的边界对齐。

      【讨论】:

        【解决方案4】:

        你可以在 for 中使用任何你想要的合法类型;它不必是完整的,甚至是内置的。例如,您也可以使用迭代器:

        for( std::vector<std::string>::iterator s = myStrings.begin(); myStrings.end() != s; ++s )
        {
        ...
        }
        

        会不会对性能产生影响,归结为你使用的算子是如何实现的问题。所以在上面的例子中,这意味着 end()、operator!=() 和 operator++()。

        【讨论】:

          【解决方案5】:

          这不是一个真正的答案。我只是在探索 Crashworks 对 PowerPC 的评价。正如其他人已经指出的那样,使用映射到本机字长的类型应该会产生最短的代码和最佳的性能。

          $ cat loop.c
          extern void bar();
          
          void foo()
          {
              int i;
          
              for (i = 0; i < 42; ++i)
                  bar();
          }
          
          $ powerpc-eabi-gcc -S -O3 -o - loop.c
          .
          .
          .L5:
                  bl bar
                  addic. 31,31,-1
                  bge+ 0,.L5
          

          short iint i 完全不同,看起来也不会表现得那么好。

          .L5:
                  bl bar
                  addi 3,31,1
                  extsh 31,3
                  cmpwi 7,31,41
                  ble+ 7,.L5
          

          【讨论】:

            【解决方案6】:

            不,它确实不应该影响性能。

            【讨论】:

              【解决方案7】:

              输入一个快速程序(您已经完成了最复杂的行)并对其进行分析可能比在这里问这个问题要快。 :-)

              FWIW,在默认使用 bignums 的语言(Python、Lisp 等)中,我从未见过循环计数器是瓶颈的配置文件。检查类型标签并不昂贵——最多几个指令——但可能比(修复)整数和短整数之间的差异更大。

              【讨论】:

                【解决方案8】:

                可能不会,只要您不使用floatdouble。由于内存很便宜,您最好只使用int

                【讨论】:

                  【解决方案9】:

                  理论上,一个 unsigned 或 size_t 应该会给你更好的结果(哇,简单的人,我们正在尝试针对邪恶进行优化,并反对那些大喊“过早”的废话。这是新趋势)。

                  但是,它也有其缺点,主要是经典的一个:搞砸了。

                  Google 开发人员似乎避免使用它,但它是对抗 std 或 boost 的皮塔。

                  【讨论】:

                  • 在哪些架构上未签名会产生更好的结果?
                  【解决方案10】:

                  如果你用优化编译你的程序(例如,gcc -O),那没关系。编译器将为该值分配一个整数寄存器,并且永远不会将其存储在内存或堆栈中。如果您的循环调用一个例程,gcc 将分配变量 r14-r31 之一,任何被调用的例程都将保存和恢复该变量。因此,请使用 int,因为这不会让阅读您的代码的人感到惊讶。

                  【讨论】:

                    猜你喜欢
                    • 2011-07-07
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-06-27
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-11-22
                    • 1970-01-01
                    • 2011-01-29
                    相关资源
                    最近更新 更多