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 Thu, 07 May 2009 04:47:18 GMT
2009/5/6 Egor Pasko <egor.pasko@gmail.com>:
> On the 0x5A9 day of Apache Harmony Ian Rogers wrote:
>> 2009/5/6 Egor Pasko <egor.pasko@gmail.com>:
>>> On the 0x5A7 day of Apache Harmony Ian Rogers wrote:
>>>> 2009/5/4 Egor Pasko <egor.pasko@gmail.com>:
>>>>> On the 0x5A5 day of Apache Harmony Tim Ellison wrote:
>>>>>> Dan Bornstein wrote:
>>>>>>> On Fri, May 1, 2009 at 4:33 AM, Egor Pasko <egor.pasko@gmail.com>
wrote:
>>>>>>>> // Non-zero and non-NaN equality checking.
>>>>>>>> if (float1 == float2 && (0.0f != float1 || 0.0f !=
float2)) {
>>>>>>>>  return 0;
>>>>>>>> }
>>>>>>>
>>>>>>> Would the following be a useful and safe improvement over the
above?:
>>>>>>>
>>>>>>>     if (float1 == float2 && 0.0f != (float1 + float2))
{
>>>>>>>
>>>>>>> I think this would save at least one test and branch. I'm not
an
>>>>>>> IEEE754 expert, but I think that, given that the two floats are
==,
>>>>>>> the second test could only be true if they are both zeroes.
>>>>>>
>>>>>> In fact, since you have the ==, why is it not sufficient to say
>>>>>>
>>>>>> (float1 == float2 && 0.0f != float1)
>>>>>>
>>>>>> Discuss :-)
>>>>>
>>>>> agreed!
>>>>>
>>>>> --
>>>>> Egor Pasko
>>>>>
>>>>>
>>>>
>>>> Also agreed with everything above :-) One final thing is that the
>>>> final comparisons of == and < could be replaced with (NB.
>>>> -Integer.MIN_VALUE == Integer.MIN_VALUE):
>>>>
>>>> return (f1 >> 32) - (f2 >> 32)
>>>>
>>>> does anyone have a performance feeling about that?
>>>
>>> If by 32 you mean 31 I have a correctness feeling in addition :)
>>
>> 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 */
>>         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.

>> - 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

Mime
View raw message