【问题标题】:Why does JDK use shifting instead of multiply/divide?为什么JDK使用移位而不是乘法/除法?
【发布时间】:2012-02-12 20:08:13
【问题描述】:

我有以下问题:

如果询问是否使用移位与乘法或除法,例如答案是,让 JVM 进行优化。

此处示例:is-shifting-bits-faster-than-multiplying

现在我正在查看 jdk 源代码,例如 Priority Queue,代码仅对乘法和除法(有符号和无符号)使用移位。

理所当然地认为 SO 中的帖子是有效答案我想知道为什么在 jdk 中他们更喜欢通过转移来做到这一点?

是不是一些与性能无关的微妙细节?我怀疑它一定与上溢/下溢乘法和除法有关,但我不确定。

有人有想法吗?使用移位是否可以更好地处理微妙的溢出问题?还是只是口味问题?

【问题讨论】:

    标签: java optimization collections bit-manipulation priority-queue


    【解决方案1】:

    我认为他们在这个特定示例中使用符号位。 Java 缺少无符号类型,因此对于使用最高有效位的数字,无法用 a /= 2 模拟 a >>> 1。请注意代码在整个示例中如何仅使用 >>>。我有理由确定这是为了充分利用整个位范围。

    【讨论】:

    • 因此对于诸如此类的微妙问题,没有移位运算符就不可能编写无错误代码?
    • @user384706 当然可以:一个简单的三元运算符在这里和那里可以帮助您解决问题。但是,效率会受到影响。
    • 能举个例子吗?我很想知道
    • @user384706 相同的原理 - 保存符号,进行无符号/有符号计算,修复结果。基本上可以用任何计算来完成。
    • @user384706 我的意思是n/2 单独是不可能的。我使用n/2、条件、按位AND 和按位OR 的组合来模拟它,因为可能会显着降低性能。
    【解决方案2】:

    除了在大多数系统上移位比除法更快之外。 >>> 执行无符号操作,除法不执行。例如如果你想要两个值的中点,你需要使用>>> 来避免溢出。 (类似代码见 Arrays.binarySearch)

    【讨论】:

    • 我想知道你为什么在第一句话中提到性能。JVM不会优化它吗?这是我从我在OP中提到的另一个SO线程中理解的
    • @LouisWasserman:所以你说我们必须始终使用移位运算符,因为 JVM 不会总是像我们预期的那样优化?在我链接到的 SO 线程中,我相信没有提到这一点
    • 我认为 JVM 在已知输入为非负但 (-1/2) == 0 和 (-1 >> 1) == -1 的情况下可能很聪明(和 -1 >>> 1 == Integer.MAX_VALUE),所以它不能只用右移替换除以 2。
    • 如果你除以n,其中n 总是2 的幂,它不会知道这一点。如果您总是按m 移动,那么您在做什么就很清楚了。如果你除以2(一个常数),它将与>> 相同,但不是>>>,因为Java 中没有无符号除以2。
    【解决方案3】:

    喜欢在 Java 中转换的一些正当理由:

    • 如果您有可能在非优化环境中运行,并且您不能保证 JIT 编译器会为您进行必要的优化。这在当今可能很少见,但在某些情况下仍可能发生。
    • 如果您真的是进行位操作而不是数值操作 - 在源代码中直接使用移位会更清楚
    • 如果您想要无符号运算(例如,您可以轻松进行无符号移位,但不能进行无符号除法)

    【讨论】:

    • 我认为原因 3 是为什么例如在优先队列实现中他们更喜欢转移?
    【解决方案4】:

    这更多的是品味问题。有些人非常习惯于二进制操作,以至于他们对他们来说更加原生(我个人也在为自己编写的代码中使用这种操作)。然而,从性能的角度来看,两者的行为是相同的(优化发生在编译时,因此使用移位将改善编译时间,但只有一小部分,你可以忽略它)。

    编辑而且我经常从我给出的每个答案中学到一些新东西:考虑this。它证明了为什么除以二不能总是优化到移位。所以我上面的评论几乎是完全错误的,只要java没有无符号类型。

    【讨论】:

    • 更一般地说:java中的JIT只有在保证数字为正的情况下才能用移位代替2的幂。如果没有,我们需要一个更复杂的例程(基本上可以归结为 3 个班次和一个无分支版本的添加,或者一个分支和添加 + 班次)
    猜你喜欢
    • 2011-04-09
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2014-08-05
    • 2013-03-22
    • 1970-01-01
    • 2014-09-12
    相关资源
    最近更新 更多