Is there still a difference between Math and StrictMath after Java 17 and JEP 306?
Asked Answered
O

1

6

JEP 306, implemented in Java 17, provides always-strict floating point semantics, deprecating the strictfp flag. Does this mean that java.lang.Math can be counted on to behave exactly the same as the analogous methods in StrictMath (i.e., that java.lang.Math methods can no longer be replaced by the JVM with intrinsics as used to be allowed)? Does it also mean that there should no longer be any differences in floating point math results among different architectures, no matter which library is used?

I'm curious if I'm misunderstanding the new Java 17 feature, since we do see differences in today's code between Apple Silicon vs Intel.

Oao answered 12/7, 2023 at 20:3 Comment(3)
What are your examples?Menchaca
+1, I appreciate that @DuncG, but will not be able to answer right away. I'll need to dig some to find sub-calculations where differences are coming up in a complex application. I'd even need to bring in another team member because I only have access to intel at the moment. We do see consistent differences in end results, though.Oao
Being strict and using intrinsics (i.e. dedicated FPU instructions) is not a contradiction. It’s all about not using the old x87 FPU but SSE2 which has been introduced 2 decades ago. In case of java.lang.Math and the reference implementation, this is the case since Java 15. This applies to the HotSpot JVM and all implementations building on it or following suit. But as long as the specification says that differences are allowed, you have to be prepared for them…Brockie
G
2

First of all, strictfp is not a flag, this is a Java keyword ensuring the same calculation results on every platform while doing operations over floating-point variables (float and double).

As of your question, there are two major PRs in OpenJDK involving the changes for JEP 306

If you look into the first one, especially into StrictMath you'll see that it now delegates directly to j.l.Math and the comment about strictfp semantics is now removed (along with strictfp keyword in OpenJDK codebase). Moreover, starting from Java 17 javac issues an explicit warning for strictfp keyword (see compiler.properties:

as of release 17, all floating-point expressions are evaluated strictly and strictfp is not required

So for the question

Does this mean that java.lang.Math can be counted on to behave exactly the same as the analogous methods in StrictMath

The answer is "yes", for some methods e.g. Math.sinh(double) delegate to StrictMath.sinh(double) (and later on to FdLibm.Sinh.compute(dobule)) and e.g. method StrictMath.toRadians(double) delegates to Math.toRadians(double). Eventually for floating-point variables it does not matter whether you call a method of Math or StrictMath, the same code is executed under the hood.

As of this part of the same question:

i.e., that java.lang.Math methods can no longer be replaced by the JVM with intrinsics as used to be allowed

The PRs does not impose any changes regarding intrinsics which are platform-specific and applied by JVM at runtime regardless of whether operation is strict or not. Moreover, as @Holger pointed out, there is no contradiction between strictness and intrinsics.

Does it also mean that there should no longer be any differences in floating point math results among different architectures, no matter which library is used?

The answer is "yes as of Java 17 or newer". Prior to it there could be difference in results, see https://mcmap.net/q/324342/-will-floating-point-operations-on-the-jvm-give-the-same-results-on-all-platforms. Before Java 17 if an operation over floating-point variable was not strict the standard assumed that

a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow. But as soon as for now the semantics is always strict you get the same result on all platforms.

See also 8268224: Cleanup references to "strictfp" in core lib comments

P.S.

we do see differences in today's code between Apple Silicon vs Intel

I think it's quite natural for compiler to produce different code for different platforms, the question here is whether you see different results of computations on mentioned platforms.

Gifted answered 8/12, 2023 at 9:15 Comment(3)
Thanks! Replying to the very last line, we are getting different results in low-order bits of calculation results, not just different code generation. One hypothesis we've come up with is that a library in use may be in a jar that was compiled pre-java17, but we haven't been able to figure out if that's what's happening. Small expressions we've tried have all given same results across architectures, so we don't have a reproducible case (MCVE) outside of cases going end-to-end in our application.Oao
@JoshuaGoldberg one more question: are the calculation results are NaNs or some 'real' values?Gifted
real values, no NaN's involved.Oao

© 2022 - 2024 — McMap. All rights reserved.