Re: [cp-patches] Float/Double compare
On Tuesday 03 July 2007 23:16:19 Ian Rogers wrote: > Here's a revised version of the patch following suggestions from Andrew > Haley. > > Ian Committed: 2007-10-12 Ian Rogers <[EMAIL PROTECTED]> 2007-10-12 Andrew Haley <[EMAIL PROTECTED]> PR classpath/33741: * java/lang/Double.java: (compare(double,double)): Increase performance of this method. * java/lang/Float.java: (compare(float,float)): Likewise. -- Andrew :)
Re: [cp-patches] Float/Double compare
Here's a revised version of the patch following suggestions from Andrew Haley. Ian --- java/lang/Float.java2006-12-10 15:25:44.0 -0500 +++ java/lang/Float.java2007-07-02 12:17:29.0 -0400 @@ -596,16 +596,25 @@ */ public static int compare(float x, float y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinities and try again -if (x == 0 && y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; + // handle the easy cases: + if (x < y) + return -1; + if (x > y) + return 1; -return x > y ? 1 : -1; + // handle equality respecting that 0.0 != -0.0 (hence not using x == y): + int ix = floatToRawIntBits(x); + int iy = floatToRawIntBits(y); + if (ix == iy) + return 0; + + // handle NaNs: + if (x != x) + return (y != y) ? 0 : 1; + else if (y != y) + return -1; + + // handle +/- 0.0 + return (ix < iy) ? -1 : 1; } } --- java/lang/Double.java 2006-12-10 15:25:44.0 -0500 +++ java/lang/Double.java 2007-07-02 12:18:36.0 -0400 @@ -587,16 +587,25 @@ */ public static int compare(double x, double y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinites and try again -if (x == 0 && y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; + // handle the easy cases: + if (x < y) + return -1; + if (x > y) + return 1; -return x > y ? 1 : -1; + // handle equality respecting that 0.0 != -0.0 (hence not using x == y): + long lx = doubleToRawLongBits(x); + long ly = doubleToRawLongBits(y); + if (lx == ly) + return 0; + + // handle NaNs: + if (x != x) + return (y != y) ? 0 : 1; + else if (y != y) + return -1; + + // handle +/- 0.0 + return (lx < ly) ? -1 : 1; } }
Re: [cp-patches] Float/Double compare
On 6/30/07, Ian Rogers <[EMAIL PROTECTED]> wrote: Attached is a patch that improves the performance of an Float/Double compare by exploiting information carried in their bit integer/long versions sign bit. It removes one comparison from the normal path, as well as making other compares with ints/longs. When sorting an array of floats this can yield a little under a 8% speed up on a Pentium 4. There's a thread discussing whether this is a good or bad idea on the main mailing list, but so far I'm merrily talking to myself :-) This is going to slow down this function for PowerPC (except for Power6+) where you have to take a huge hit to transfer between register sets via the stack. For an example on the Cell, this is going to be an extra 40-100 cycle hit. -- Pinski
Re: [cp-patches] Float/Double compare
Andrew Pinski wrote: On 6/30/07, Ian Rogers <[EMAIL PROTECTED]> wrote: Attached is a patch that improves the performance of an Float/Double compare by exploiting information carried in their bit integer/long versions sign bit. It removes one comparison from the normal path, as well as making other compares with ints/longs. When sorting an array of floats this can yield a little under a 8% speed up on a Pentium 4. There's a thread discussing whether this is a good or bad idea on the main mailing list, but so far I'm merrily talking to myself :-) This is going to slow down this function for PowerPC (except for Power6+) where you have to take a huge hit to transfer between register sets via the stack. For an example on the Cell, this is going to be an extra 40-100 cycle hit. I guess there are a lot of factors to do with the underlying architecture. My feeling is that we should move the code to VMFloat/VMDouble and then the VM can choose the appropriate version. Having the regular version optimized for Intel would make sense to me. Its not straight forward for me to benchmark the code on non-IA32 architectures, in particular Cell. I'll try to do a Jikes RVM benchmark on a PowerPC I have access to in the week. My feeling is that the performance may not be as bad as you imagine, but it's hard to predict - and this may not be an architecture you care about anyway. Regards, Ian
[cp-patches] Float/Double compare
Attached is a patch that improves the performance of an Float/Double compare by exploiting information carried in their bit integer/long versions sign bit. It removes one comparison from the normal path, as well as making other compares with ints/longs. When sorting an array of floats this can yield a little under a 8% speed up on a Pentium 4. There's a thread discussing whether this is a good or bad idea on the main mailing list, but so far I'm merrily talking to myself :-) Ian --- java/lang/Double.java 2006-12-10 20:25:44.0 + +++ java/lang/Double.java 2007-06-30 22:21:39.98610 +0100 @@ -587,16 +587,17 @@ */ public static int compare(double x, double y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinites and try again -if (x == 0 && y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; - -return x > y ? 1 : -1; +long lx = doubleToLongBits(x); +long ly = doubleToLongBits(y); +if (lx == ly) return 0; +if (isNaN(x)) return 1; +if (isNaN(y)) return -1; +int lx_sign = (int)(lx>>63); +int ly_sign = (int)(ly>>63); +if (lx_sign == ly_sign) { + return x > y ? 1 : -1; +} else { + return lx_sign - ly_sign; +} } } --- java/lang/Float.java2006-12-10 20:25:44.0 + +++ java/lang/Float.java2007-06-30 22:10:46.099648000 +0100 @@ -596,16 +596,17 @@ */ public static int compare(float x, float y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinities and try again -if (x == 0 && y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; - -return x > y ? 1 : -1; +int ix = floatToIntBits(x); +int iy = floatToIntBits(y); +if (ix == iy) return 0; +if (isNaN(x)) return 1; +if (isNaN(y)) return -1; +int ix_sign = ix>>31; +int iy_sign = iy>>31; +if (ix_sign == iy_sign) { + return x > y ? 1 : -1; +} else { + return ix_sign - iy_sign; +} } }