JDK 9 RFR of JDK-8134795: Port fdlibm pow to Java
joe darcy
joe.darcy at oracle.com
Wed Sep 16 16:58:15 UTC 2015
Hi Volker,
On 9/16/2015 2:02 AM, Volker Simonis wrote:
> Hi Joe,
>
> nice clean-up! From a maintenance point of view the the old fdlibm has
> been a burden and a constant source of warnings with newer compilers.
>
> What about the final arrays in Pow.compute (BP, DP_H, DP_L). In the
> Interpreter (and even in C2 without EscapeAnalysis) this will lead to
> allocations every time the method is called. Making them static fields
> of 'Pow' will help here. On the other hand, if the arrays are static
> fields of 'Pow', C2 will not be able to directly use the constants but
> will have to load them from the array. So altogether, your current
> implementation is optimal with HotSpot (with EscapeAnalysis turned on
> by default) but might not be the best for other VMs without
> EscapaAnalysis.
>
> Have you done any benchmarking which compares the new Java against the
> old C implementation?
>
>
I don't have exact stats to share, but some quick benchmarks indicate it
is noticeably faster, more than 10%. The less computation pow does in a
given case, the faster the Java version should be since the Java -> C ->
Java cost should roughly be fixed.
Once the code is fully in Java, I would expect further tweaks to refine
the code. For example, the original FDLIM code used the idiom of pointer
aliasing a two-element int array with a double. (This idiom was also the
source of many of those compiler warnings ;-) We can't directly use that
idiom in Java, but the early versions of the port were a close
transliteration of the C sources with equivalent Java method calls. That
still left the code as operating on 32-bit quantities or doing
comparisons of the double value by looking at its 32 high-order bits.
Many of those 32-bit operations were removed as the port progressed to
use clearer (if not also faster) operations such as comparing 64-bit
double values directly as 64-bit double values.
For example, to my eye I'd much rather read
185 // Special value of x
186 if (x_abs == 0.0 ||
187 x_abs == INFINITY ||
188 x_abs == 1.0) {
189 z = x_abs; // x is +/-0, +/-inf, +/-1
190 if (y < 0.0)
191 z = 1.0/z; // z = (1/|x|)
where x_abs is a double holding the absolute value of x, than the
original semantically equivalent original
178 /* special value of x */
179 if(lx==0) {
180 if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
181 z = ax; /*x is +-0,+-inf,+-1*/
182 if(hy<0) z = one/z; /* z = (1/|x|) */
where lx is the lower-order 32 bits of x and ix is the high-order 32
bits of x with the sign bit zeroed out.
The version sent out for review still has some remaining 32-bit centered
operations and at least some of those could be eliminated.
Thanks,
-Joe
More information about the core-libs-dev
mailing list