Java中Math.pow(x,2.0)与Math.pow(x,2.0000001)的性能对比

6
我试图比较pow(x,2.0)pow(x,2.0000001)的性能,我认为2.0会更快,但它们的速度相同。我甚至通过使用-Xint参数运行jar文件来删除JIT优化。
请问这是为什么呢?
非常感谢!

1
实现可以自由地使用条件分支来测试特殊情况或者使用相同的代码实现所有情况。重要的是结果。执行时间没有任何保证。(并不是说,如果你不小心,就算有保证也看不到它们)。 - Pascal Cuoq
因为它只使用了一个专门针对所有双精度浮点数的神奇实现;它没有使用任何整数幂的特殊魔法。如果你直接使用乘法(x * x),你会得到更好的结果。 - Louis Wasserman
1
我期望有更好的结果,因为Math.pow(x,y)的源代码对于y==2有返回条件,你可以在这里看到: http://developer.classpath.org/doc/java/lang/StrictMath-source.html - Tomáš Mocek
1
@TomášMocek,也许Math.pow(而不是你提到的StrictMath.pow)不区分指数? - s.bandara
谢谢大家的回答,java -version 打印出 1.7.0_51,Java SE Runtime Environment 等信息,所以我猜你们关于 GNU Classpath 的说法是正确的,对吗?此外,感谢 s.bandara,当我尝试使用 StrictMath.pow() 而不是 Math.pow() 时,结果如预期。 - Tomáš Mocek
显示剩余3条评论
1个回答

11
尽管问题收到了不公平的负评,但它确实很有意义,因为它揭示了真正的JVM缺陷。 当您运行Oracle JDK时,Math.pow(x, 2.0)的性能在JVM版本之间高度变化。
- 在JDK 7u40之前,Math.pow使用软件实现,即仅调用__ieee754_pow函数在软件中模拟操作。它非常慢,但对于 y == 2 有特殊情况。 - 自JDK 7u40以来,Math.pow成为JVM内置函数,由JIT翻译为FPU指令。然而,这种优化丢失了特殊情况,导致y == 2 的性能回归,参见bug JDK-8029302。 - 这个性能回归已在JDK 8u25和即将到来的7u80中得到修复。自JDK 8u25以来,Math.pow对于所有值的工作速度都足够快,但对于y == 2来说极快。请参见相关问题P.S.在我的机器上,使用不同版本的JDK对100M个Math.pow调用的大致时间(以秒为单位)。
             Math.pow(x, 2.0)    Math.pow(x, 2.0000001)
JDK 7u25            3.0                30.4
JDK 7u40           11.1                11.1
JDK 8u40            0.1                11.1      

1
当你说“Java实现”时,实际上是指本地方法,对吗? - Marko Topolnik
1
从链接的JDK错误报告中引用:“使用“-XX:+ UnlockDiagnosticVMOptions -XX:+ PrintIntrinsics”显示内在实现在两种情况下都被使用。” 因此,实际更改只发生在内在本身,而不是引入内在的事实。 - Marko Topolnik
2
@MarkoTopolnik 嗯,这是一个相当愚蠢的内置函数。我的意思是它没有遍历所有JNI内容(在这个意义上它是一个“内置函数”),但它仍然必须调用仿真函数的本地调用。在JDK7u40中,它成为了一个“真正的内置函数”,也就是说,实现是用汇编语言编写的,并且被内联到调用者中。我已经更新了答案,使其更加精确。感谢您的审查 :) - apangin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接