harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ian Rogers <ian.rog...@manchester.ac.uk>
Subject Re: Float/Double comparison performance
Date Fri, 08 May 2009 13:39:50 GMT
2009/5/7 Egor Pasko <egor.pasko@gmail.com>:
> On the 0x5AA day of Apache Harmony Ian Rogers wrote:
>> 2009/5/6 Egor Pasko <egor.pasko@gmail.com>:
>>>> Thanks Egor :-) I don't know if 3 dependent integer operations will
>>>> run faster than two compare and branches as the branches may be
>>>> speculated over. Unfortunately for Jikes RVM we frequently sort arrays
>>>> containing just 0.0 and 1.0 meaning the performance of 0.0 compares
>>>> hurts us.
>>>
>>> Ian, do you really need zeroes in the right order? I'd be really
>>> surprized if you do :) If there are really a lot of +-0.0s .. isn't it
>>> faster to count the number of zeroes prior to sorting?
>>
>> Agreed, I'm being lazy in not writing our own sort :-)
>>
>>>> Other issues if we're wringing performance:
>>>>
>>>> - could Float.equals be improved in a similar manner to
>>>> Float.compareTo in particular avoiding using floatToIntBits and its
>>>> inherent NaN tests,ie:
>>>>
>>>>     public boolean equals(Object object) {
>>>>         /* removed as this case seems generally unlikely and is
>>>> covered by the case below
>>>>         if (object == this) {
>>>>            return true;
>>>>         } else */
>
> By the way, I am not eager to disable this (speculative)
> optimization. Can you prove that your new version behaves better on
> common benchmarks?

Sorry no, I was just imagining something like a  HashSet containing
100 boxed floats, the chance that the two identities will be the same
is very small - say 1 in 100 if we're searching an element already in
the HashSet, lower if not. I'm not aware of a common benchmark where
this is a performance issue anyway.

>>>>         if (object instanceof Float) {
>>>>              float otherValue = ((Float) object).value;
>>>>              return (floatToRawIntBits(value) ==
>>>> floatToRawIntBits(otherValue)) ||
>>>>                  (isNaN(value) && isNaN(otherValue));
>>>>         } else {
>>>>            return false;
>>>>         }
>>>>     }
>>>
>>> is compareTo not suitable here because of the same reasons as in
>>> example below? Or am I missing something?
>>
>> The current equals code doesn't use compareTo and the < and > cases
>> aren't that interesting, the code above is really just putting the
>> same optimizations discussed for compareTo into place for equals.
>
> OK, cool.
>
> not sure I understand the reason to change floatToIntBits() to
> floatToRawIntBits() in the above and comparing with NaN
> explicitly. floatToIntBits() replaes the isNaN() checking at a low
> cost. Most of the time is eaten in JNI transition, I believe.

So we removed the JNI transition and just use an intrinsic operation
in the case of the raw bits. Our operation for non raw bits is:

static int floatToIntBits(float value) {
  if (isNaN(value)) return Float.NaN;
  else return floatToRawIntBits(value);
}

The floatToRawIntBits of a value in an object on x86 ends up compiling
down to an integer load (move) from memory - or if this value is
compared it can just be a memory operand to a compare instruction (we
use a BURS based instruction selector). The isNaN requires a floating
point comparison, so in the current code we do two isNaN floating
point comparisons prior to the fast raw bit comparison - my change
just moves the isNaN tests to after the raw bit comparison has failed
as I assume NaN is unlikely.

Regards,
Ian

>>>> - is it worth specializing the code in Arrays.lessThan to something
>>>> like (I don't think Jikes RVM can inline compareTo and achieve an
>>>> equivalent transformation and it saves quite a number of compares):
>>>>
>>>>     private static boolean lessThan(float float1, float float2) {
>>>>         // Non-zero, non-NaN checking.
>>>>         if (float2 > float1) {
>>>>             return true;
>>>>         }
>>>>         if (float1 >= float2 && 0.0f != float1) {
>>>>             return false;
>>>>         }
>>>>         // NaNs are equal to other NaNs and larger than any other float
>>>>         if (isNaN(float1)) {
>>>>             return false;
>>>>         } else if (isNaN(float2)) {
>>>>             return true;
>>>>         }
>>>>         // Deal with +0.0 and -0.0
>>>>         int f1 = floatToRawIntBits(float1);
>>>>         int f2 = floatToRawIntBits(float2);
>>>>         return f1 < f2;
>>>>     }
>>>
>>> good idea, I'll do that if nobody objects :)
>>
>> Cheers,
>> Ian
>>
>
> --
> Egor Pasko
>
>

Mime
View raw message