【问题标题】:which one is faster 5+5+5+5+5 or 5*5?5+5+5+5+5 还是 5*5 哪个更快?
【发布时间】:2011-06-13 01:43:53
【问题描述】:

我不知道怎么问,只是想问。请帮我标记它。无论如何,我的朋友问我一个问题,在 Java 中哪个更快

int a = 5 + 5 + 5 + 5 + 5

int b = 5 * 5 ?

它依赖于语言吗?我的意思是,a 在 java 中比 b 快​​,但在 C 中则不然

我的答案是 ab 快,因为计算机组织中的加法/乘法比较

【问题讨论】:

  • 我认为你很难在这里衡量性能,这在很大程度上取决于你(或 JIT)正在使用什么优化设置,也可能取决于下面的硬件。特别是,我希望您的示例中的常量案例在编译时都被编译器优化为 25。

标签: java performance language-agnostic optimization math


【解决方案1】:

它依赖于平台(和编译器)。如果您需要知道,请测量它。您不太可能会遇到需要知道的情况。

但是,在您的两个示例中,这些都将在编译时进行评估(因此不需要运行时计算);参见例如http://en.wikipedia.org/wiki/Constant_folding.

【讨论】:

  • 我只是从理论上回答这个问题,加法是好的。测量对它来说不是问题,如果 5+5+....+5 怎么办?
  • @hilal:嗯,一方面,你不能用代码中的 5 + 5 + 5 + ... + 5 来表达 5n,除非你使用循环。甚至 then 我认为一些编译器只会优化循环。
  • @BoltClock 是的,一些编译器甚至不会生成循环代码,如果它根本没有可观察到的副作用 xD
【解决方案2】:

在你的情况下不会改变任何东西。让我们编译:

public class Toto {
    public static void main(String[] args) {
        int a = 5 + 5 + 5 + 5 + 5;
        int b = 5 * 5;
    }
}

并查看反编译结果:

public class Toto
{
    public static void main(String args[])
    {
        byte byte0 = 25;
        byte byte1 = 25;
    }
}

编译器确实内联了所有内容。

【讨论】:

    【解决方案3】:

    都是常量表达式,所以会简化为

    int a = 25;
    int b = 25;
    

    在编译时(100% 肯定,即使是玩具编译器也会这样做,因为这是最简单的优化之一)。

    在远程情况下,这些操作没有简化,假设有一个 JIT 将乘法和加法操作码以 1:1 的关系映射到它们的 CPU 指令对应物,在大多数现代架构中,所有整数算术运算通常采用相同的周期数,所以乘法一次比加四次要快(刚刚检查过,加法仍然比乘法快一点:1 个时钟对 3 个时钟,所以在这里使用乘法仍然是值得的)。

    即使在超标量架构中,每个周期可以发出多个指令,加法操作链也具有数据依赖性,因此它们必须按顺序执行(由于加法指令只有 1 个周期,没有可能的管道重叠,仍然需要 4 个周期)。

    在大多数 CPU 架构中,最佳指令序列可能是向左移动两个位置,然后添加原始值 (5<<2+5)。

    【讨论】:

    • 我不这么认为。他们不能相等
    • 幸好,现实并不在乎你喜不喜欢。
    • 我不是在谈论形而上学。在这种情况下,阅读一本书并了解正在发生的事情非常简单。
    • 这就引出了一个编译更快的问题。也可能没有。
    【解决方案4】:

    这里至少有两个问题:底层操作的性能,以及编译器做了什么。 (事实上​​,Java-to-bytecode 编译器和 JIT 编译器都是这样做的。)

    首先,“原始”操作的问题。作为一般规则,加法、减法和乘法在大量处理器上花费的时间大致相同。你可能会想象乘法会慢很多,但事实并非如此。例如,查看各种处理器上的 paper giving some experimental timings of X86 instructions。乘法总体上稍微“慢”一点,因为它具有更高的延迟。这实际上意味着,如果处理器只对不同的数据块执行一系列乘法运算,那么它会比对不同的数据块执行一系列加法运算稍慢。但是,如果有其他指令可以在“乘法完成时”执行,那么加法和乘法之间总体上并没有太大区别。

    不久前,我还在 32 位 Pentium 上列出了 timings of floating point instructions used by Hotspot 的列表(这些数字最初来自英特尔的处理器手册,我记得我做过实验测试,实际上这些是你得到的时间) .请注意,有一种非常相似的模式:加法、减法和乘法本质上彼此花费相同的时间;除法速度明显较慢。

    然后,如果您查看我刚刚提到的页面上的表格,您会发现除以 2 的幂更快,因为 JIT 编译器可以将这些转换为乘法。 2 的幂可以用浮点表示精确地表示,因此如果将除以 x 除以乘以 1/x,其中 x 是 2 的幂,则不会损失精度。

    或者换句话说,Java 编译器和 JIT 编译器都可以应用各种优化,这意味着给定代码段的底层指令不一定是您认为的那样。正如其他人所提到的,一个非常基本的优化是预先计算值,所以如果你写“5+5+5+5+5”,实际上Java编译器应该用“25”替换它。

    【讨论】:

      【解决方案5】:

      这完全取决于您使用的环境:

      • 哪个编译器?好不好,然后编译成常量。

      • 程序代码的其余部分是什么?如果不使用结果,则都编译为 NOP(无操作)。

      • 它在哪个硬件上运行?如果您的处理器针对乘法而非加法进行了超级优化,则乘法(理论上)可能比加法运算更快

      在大多数情况下,您不应该关心什么更快,大多数编译器都比您更聪明,并且会为您优化。

      如果您真的关心它,您可能不会在这里问这个问题,但在这种情况下:对其进行基准测试。创建两个程序 A 和 B,在典型的现实生活场景中使用它们,测量时间/能量/您感兴趣的任何参数,根据结果确定哪个程序更适合您的需求。

      【讨论】:

        【解决方案6】:

        我们应该比较时间复杂度。函数是f1(n) = n * c,相当于f2(n) = Sum[1->n] c

        乘法的复杂度是O(1)(常数时间,任何n计算一次),加法的复杂度是O(n)(线性时间,加法的次数等于n)。

        【讨论】:

        • n 没有改变它也是 O(1)。 5+5+5和5*3
        • @hilal - 调整了函数,但结果是一样的。乘法 O(1),加法 O(n)(一般)
        【解决方案7】:

        这取决于编译器,因为每个编译器对此都有不同的机制,有些使用左移操作,有些使用另一种机制。

        但在许多情况下,加法比乘法快。

        【讨论】:

          【解决方案8】:

          我猜加法比乘法快,因为(据我所知)所有乘法都被视为加法

          添加:

          阅读 here 以获得一些解释

          【讨论】:

          • -1:在大多数现代平台上,都有一个硬件乘法器。即使是像 PIC 微控制器这样简单的东西也经常有一个。
          猜你喜欢
          • 2021-04-01
          • 2013-11-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-18
          • 2018-07-23
          • 1970-01-01
          相关资源
          最近更新 更多