[JBS] {New} (JDK-8170430) x86 pow() stub from Intel libm is inconsistent with pow() from fdlib
joe darcy
joe.darcy at oracle.com
Wed Nov 30 21:02:31 UTC 2016
Hello,
It is allowed by the specification and desirable for Math.pow to return
different results than StrictMath.pow, subject to the quality of
implementation criteria governing both implementations.
For pow those requirements are:
The computed result must be within 1 ulp of the exact result.
Results must be semi-monotonic.
http://download.java.net/java/jdk9/docs/api/java/lang/Math.html#pow-double-double-
Having "the computed result must be within 1 ulp of the exact result"
means (in summary) one of the the two floating-point values bracketing
the exact mathematical result must be returned. Requiring the results to
be "semi-monotonic" means that when the true pow function is increasing
the floating-point approximation must be non-decreasing. A particular
example, fix the first argument of pow to be some finite X > 1 and for
successive finite floating-point numbers y1, y2, y3, ... all > 1 it is
true mathematically that:
pow(X, y1) < pow(X, y2) < pow(X, y3) < ...
and thus by the semi-monotonic requirement the floating-point
approximation must have the property that:
pow(X, y1) <= pow(X, y2) <= pow(X, y3) <= ...
Say you have two pow implementations, pow1 and pow2, that separately
mean the accuracy and semi-monotonic requirements above. Is some
interleaving of pow1 and pow2 also a valid implementation?
Since each of pow1 and pow2 meet the accuracy requirements for a given
argument, picking one or another is fine. However, the semi-monotonic
requirement can be problematic. For example, lets say in a flat portion
of the graph we have a true mathematical result close to (a+ b)/2 with a
< b and pow1 and pow2 behaving as follows:
pow1(X, y1) = a
pow1(X, y2) = a
pow1(X, y3) = a
pow2(X, y1) = b
pow2(X, y2) = b
pow2(X, y3) = b
Separately, each of pow1 and pow2 is meeting the accuracy and
semi-monotonic requirements.
However, if an interleaving pow picks pow2 for (X, y1) and pow1 for (X,
y2), the semi-monotonic requirement will be violated and the composite
implementation *illegal*.
Just picking one of pow1 and pow2 and sticking with it for a given JVM
run avoids having to worry about such subtle issues. For that reason,
we've worked to make the math instrinics behave consistently independent
of being run in the interpreter, C1, C2, and so on. Various bugs to
implement such consistency have been filed and fixed over the years, but
I'm dig them up at this time.
In this case, I strongly recommend the pow stub be used or not used
independent of what HotSpot compiler is run.
HTH,
-Joe
On 11/30/2016 10:25 AM, Vladimir Kozlov wrote:
> On 11/30/16 9:35 AM, Volker Simonis wrote:
>> Hi,
>>
>> what is the actual problem here? Is it the fact that Math.pow()
>> returns different results depending on whether it is executed in
>> interpreted or in JIT-compiled mode?
>>
>> Or in other words - do we insist on having the same results from the
>> Math functions while promoting from Interpreted to C1 and finally C2?
>
> Yes, that is the goal. The result should be the same from Interpreter
> and from code generated by JIT compilers.
>
>> The API-doc for Math says: "Unlike some of the numeric methods of
>> class StrictMath, all implementations of the equivalent functions of
>> class Math are not defined to return the bit-for-bit same results.
>> This relaxation permits better-performing implementations where strict
>> reproducibility is not required." But I'm not sure if this implies
>> that Math.FUNC(constant_value) always has to return the bit-for-bit
>> same result no matter how often we call it?
>>
>> The problem is that by default the Java implementation of the Math
>> functions call the StrictMath version. So if the interpreter does no
>> optimizations, it will get the exact StrictMath (i.e. fdlibm) results.
>> But when the Math methods are compiled, they may be intrinisfied, in
>> which case they are allowed to return less exact values. A further
>> complication is that the interpreter may optimize himself and either
>> use optimized assembler stubs for a function (e.g.
>> StubRoutines::_dsin()) or uses leaf-calls into HotSpots internal
>> C++-Implementation of the functions (e.g. SharedRuntime::dsin()).
>
> JIT compilers should follow the same rule as Interpreter: call
> StubRoutines::_dsin or SharedRuntime::dsin.
>
>>
>> So what does "strict reproducibility is not required" for Math
>> functions actually mean? Is it OK for a program like this:
>>
>> while(true) {
>> if (Math.FUNC(val) == XXX) System.out.println("YES");
>> else System.out.println("NO");
>> }
>>
>> to print both, "YES" and "NO"?
>
> No, we try to avoid this. During application one run the answer should
> be the same regardless how frequent a method is executed (JITed or
> not). But the result does not necessary need to be the same when an
> application run with different flags (InlineIntrinsics).
>
> This is how I understand it.
>
> We had a lot of bugs (for pow() especially) when results were
> inconsistent during run until we start using the same code in
> Interpreter and JITed code.
>
> Regards,
> Vladimir
>
>>
>> Thank you and best regards,
>> Volker
>>
>>
>> On Wed, Nov 30, 2016 at 2:34 AM, Vladimir Kozlov
>> <vladimir.kozlov at oracle.com> wrote:
>>> Thank you, Vivek
>>>
>>> I will sponsor it.
>>>
>>> Do you think it is hard to fix stubs code even in some next release?
>>>
>>> Thanks,
>>> Vladimir
>>>
>>>
>>> On 11/29/16 5:26 PM, Deshpande, Vivek R wrote:
>>>>
>>>> Hi
>>>>
>>>>
>>>>
>>>> I have bug fix for avx512 8170430.
>>>>
>>>> http://cr.openjdk.java.net/~vdeshpande/8170430/webrev.00/
>>>>
>>>> I have also updated the JBS entry.
>>>>
>>>> https://bugs.openjdk.java.net/browse/JDK-8170430
>>>>
>>>> I have tested it with other libm stubs too along with pow.
>>>>
>>>> Would you please review and sponsor it.
>>>>
>>>>
>>>>
>>>> Regards,
>>>>
>>>> Vivek
>>>>
>>>>
>>>
More information about the hotspot-compiler-dev
mailing list