Fwd: The result of Math.log(3.0) is different on x86_64 and aarch64?

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Fwd: The result of Math.log(3.0) is different on x86_64 and aarch64?

Sean Owen-2
That is really interesting re: the recent threads about the value of
log() and pow() in the JVM. I think it's worth copying to dev@ here.

---------- Forwarded message ---------
From: Tianhua huang <[hidden email]>
Date: Mon, Jul 29, 2019 at 5:28 AM
Subject: Fwd: The result of Math.log(3.0) is different on x86_64 and aarch64?
To: Sean Owen <[hidden email]>

Sorry to disturb you, I forward the jdk-dev email to you, maybe you
are interesting :)

---------- Forwarded message ---------
From: Pengfei Li (Arm Technology China) <[hidden email]>
Date: Mon, Jul 29, 2019 at 5:52 PM
Subject: RE: The result of Math.log(3.0) is different on x86_64 and aarch64?
To: bo zhaobo <[hidden email]>, Tianhua huang
<[hidden email]>, Deshpande, Vivek R
<[hidden email]>
Cc: [hidden email] <[hidden email]>,
[hidden email] <[hidden email]>,
nd <[hidden email]>

Hi Bo, Tianhua,

Thanks for reporting this issue. You could CC
[hidden email] if you find something strange on
AArch64 server next time.

> >> Sorry to disturb you again, I took some tests of java.lang.Math.log
> >> function on aarch64 server, I met a strange case, the result of
> >> Math.log(3.0) is different with x86_64:
> >> on x86_64:
> >> scala> Math.log(3.0) res50: Double = 1.0986122886681098
> >>
> >> but on aarch64:
> >> scala> Math.log(3.0) res19: Double = 1.0986122886681096

I've reproduced this on both JDK12 and latest JDK master (14) with
below Java code.

public class Test {
  public static void main(String[] args) {
    double d = Math.log(3.0);
    String hex = Long.toHexString(Double.doubleToRawLongBits(d));
    System.out.println(d + "(0x" + hex + ")");

(x86_64)~$ java Test
(aarch64)~$ java Test

From above results we see the least significant bit differs on aarch64
from that on x86_64. So which one is more accurate?

By exploring HotSpot code, we could see a method "__ieee754_log(double
x)"[1] in shared (architecture independent) code which computes the
log(double). But this SharedRuntime method is called only if the
architecture specific "StubRoutine::dlog()" is NULL. See [2] for this
logic in the C2 compiler but there is no big difference in C1 or the
interpreter. I.e. The Math.log(3.0) actually calls into some
hand-crafted assembly code if it's generated. By looking into the
cpu-specific stuff, we could found that the log() routine is generated
on x86_64[3], but disable on aarch64[4] due to issues found before.

In another word, the Math.log() call is optimized by HotSpot
intrinsics located at [5] on x86_64 but just uses __ieee_754_log() on
aarch64. To prove what I've seen is right, I tested my above Java code
with VM options "-XX:+UnlockDiagnosticVMOptions
-XX:-InlineMathNatives" on both x86_64 and aarch64.

(x86_64)~$ java -XX:+UnlockDiagnosticVMOptions -XX:-InlineMathNatives Test
(x86_64)~$ java Test

(aarch64)~$ java -XX:+UnlockDiagnosticVMOptions -XX:-InlineMathNatives Test
(aarch64)~$ java Test

From the results we see that, if we have the assumption shared method
__ieee754_log(double) is correct, there should be nothing wrong in
aarch64 HotSpot. Instead, the x86_64 log intrinsics may have done some
optimization that destroys the accuracy. We need an Intel engineer
(maybe ~vdeshpande) to look at the code.

[1] http://hg.openjdk.java.net/jdk/jdk/file/2116221e2dde/src/hotspot/share/runtime/sharedRuntimeTrans.cpp#l113
[2] http://hg.openjdk.java.net/jdk/jdk/file/2116221e2dde/src/hotspot/share/opto/library_call.cpp#l1870
[3] http://hg.openjdk.java.net/jdk/jdk/file/2116221e2dde/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp#l5906
[4] http://hg.openjdk.java.net/jdk/jdk/file/2116221e2dde/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp#l5700
[5] http://hg.openjdk.java.net/jdk/jdk/file/2116221e2dde/src/hotspot/cpu/x86/macroAssembler_x86_log.cpp#l185


To unsubscribe e-mail: [hidden email]