[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