On 25 March 2013 11:44, Luc Maisonobe <luc.maison...@free.fr> wrote:
> Le 25/03/2013 11:50, sebb a écrit :
>> On 25 March 2013 10:46,  <l...@apache.org> wrote:
>>> Author: luc
>>> Date: Mon Mar 25 10:46:42 2013
>>> New Revision: 1460604
>>>
>>> URL: http://svn.apache.org/r1460604
>>> Log:
>>> Improved speed of FastMath.abs methods, by removing branching.
>>>
>>> JIRA: MATH-954
>>>
>>> Modified:
>>>     commons/proper/math/trunk/src/changes/changes.xml
>>>     
>>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
>>>
>>> Modified: commons/proper/math/trunk/src/changes/changes.xml
>>> URL: 
>>> http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1460604&r1=1460603&r2=1460604&view=diff
>>> ==============================================================================
>>> --- commons/proper/math/trunk/src/changes/changes.xml (original)
>>> +++ commons/proper/math/trunk/src/changes/changes.xml Mon Mar 25 10:46:42 
>>> 2013
>>> @@ -55,10 +55,13 @@ This is a minor release: It combines bug
>>>    Changes to existing features were made in a backwards-compatible
>>>    way such as to allow drop-in replacement of the v3.1[.1] JAR file.
>>>  ">
>>> +      <action dev="luc" type="update" issue="MATH-954" due-to="Charles 
>>> Cooper">
>>> +        Improved speed of FastMath.abs methods for all signatures, by 
>>> removing branching.
>>> +      </action>
>>>        <action dev="luc" type="update" issue="MATH-953" due-to="Charles 
>>> Cooper">
>>>          Improved speed of several FastMath methods.
>>>        </action>
>>> -        <action dev="luc" type="fix" issue="MATH-934">
>>> +      <action dev="luc" type="fix" issue="MATH-934">
>>>          Fixed Complex.reciprocal() for zero argument.
>>>        </action>
>>>        <action dev="luc" type="update" issue="MATH-951" due-to="Charles 
>>> Cooper">
>>>
>>> Modified: 
>>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
>>> URL: 
>>> http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java?rev=1460604&r1=1460603&r2=1460604&view=diff
>>> ==============================================================================
>>> --- 
>>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
>>>  (original)
>>> +++ 
>>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
>>>  Mon Mar 25 10:46:42 2013
>>> @@ -2987,7 +2987,8 @@ public class FastMath {
>>>       * @return abs(x)
>>>       */
>>>      public static int abs(final int x) {
>>> -        return (x < 0) ? -x : x;
>>> +        final int i = x >>> 31;
>>> +        return (x ^ (~i + 1)) + i;
>>
>> Are we sure that's faster?
>>
>> Surely branches aren't significantly slower than arithmetic operations.
>
> The tests I did using Gilles PerfTestUtils show an improvement. Not a
> very big one (about 5%), but an improvement.
>
> The reason for that is most probably branch prediction errors at
> processor level. Once code has been inlined and compiled to native code,
> the prediction of the branch to follow (if or else) drives the speed. As
> for an abs() method, I think branch prediction is 50% true, 50% false
> (it is not the same for a loop for example, as for example if you
> iterate 10 times, it means the condition will be to stay in the loop 9
> times and to exit only 1 time).

What about

if (x >= 0) return x;
return -x;

Would that be any faster?
It's simpler to read.

> Luc
>
>>
>>>      }
>>>
>>>      /**
>>> @@ -2996,7 +2997,12 @@ public class FastMath {
>>>       * @return abs(x)
>>>       */
>>>      public static long abs(final long x) {
>>> -        return (x < 0l) ? -x : x;
>>> +        final long l = x >>> 63;
>>> +        // l is one if x negative zero else
>>> +        // ~l+1 is zero if x is positive, -1 if x is negative
>>> +        // x^(~l+1) is x is x is positive, ~x if x is negative
>>> +        // add around
>>> +        return (x ^ (~l + 1)) + l;
>>>      }
>>>
>>>      /**
>>> @@ -3005,7 +3011,10 @@ public class FastMath {
>>>       * @return abs(x)
>>>       */
>>>      public static float abs(final float x) {
>>> -        return (x < 0.0f) ? -x : (x == 0.0f) ? 0.0f : x; // -0.0 => +0.0
>>> +        if ((Float.floatToRawIntBits(x) & Integer.MIN_VALUE) == 0) {
>>> +            return x;
>>> +        }
>>> +        return -x;
>>>      }
>>>
>>>      /**
>>> @@ -3014,7 +3023,10 @@ public class FastMath {
>>>       * @return abs(x)
>>>       */
>>>      public static double abs(double x) {
>>> -        return (x < 0.0) ? -x : (x == 0.0) ? 0.0 : x; // -0.0 => +0.0
>>> +        if ((Double.doubleToRawLongBits(x) & Long.MIN_VALUE) == 0) {
>>> +            return x;
>>> +        }
>>> +        return -x;
>>>      }
>>>
>>>      /**
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
>> For additional commands, e-mail: dev-h...@commons.apache.org
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to