You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Gilles Sadowski <gi...@gmail.com> on 2020/01/14 12:14:51 UTC

Re: [commons-numbers] branch master updated: Add benchmark for sin/cos computation.

Hi.

Le mar. 14 janv. 2020 à 12:24, <ah...@apache.org> a écrit :
>
> [...]
>
>     Add benchmark for sin/cos computation.
>
>     Computing sin/cos together would improve many of the functions in
>     Complex. This benchmark investigates the possibility of using the
>     Commons FastMath implementation instead of java.util.Math.

Related issues:
https://issues.apache.org/jira/browse/MATH-901
https://issues.apache.org/jira/browse/MATH-1113
https://issues.apache.org/jira/browse/MATH-740

But CM does not provide sine and cosine in a single function call.

Regards,
Gilles

> [...]

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


Re: [commons-numbers] branch master updated: Add benchmark for sin/cos computation.

Posted by Alex Herbert <al...@gmail.com>.
On 14/01/2020 12:14, Gilles Sadowski wrote:
> Hi.
>
> Le mar. 14 janv. 2020 à 12:24, <ah...@apache.org> a écrit :
>> [...]
>>
>>      Add benchmark for sin/cos computation.
>>
>>      Computing sin/cos together would improve many of the functions in
>>      Complex. This benchmark investigates the possibility of using the
>>      Commons FastMath implementation instead of java.util.Math.
> Related issues:
> https://issues.apache.org/jira/browse/MATH-901
> https://issues.apache.org/jira/browse/MATH-1113
> https://issues.apache.org/jira/browse/MATH-740

Thanks for the links.

Most of this discussion is that speed can be improved but it seems to be 
at the loss of accuracy. I would err on the side of accuracy rather than 
speed. Ideally a sin/cos implementation should be within 1 ULP of the 
actual result as per java.util.Math.

>
> But CM does not provide sine and cosine in a single function call.

But it could. Both sin and cos first assign the input number x to a 
quadrant in the range -pi to pi. This could be shared by a sin/cos 
implementation.

Looking at the code it seems that the assignment to a quadrant may not 
be the significant part of the run-time. I am going to investigate this 
using a profiler to check.

There are a few scenarios to consider:

edge cases: NaN, Inf, 0

These have a definite result that can be computed for both sin and cos 
together.

Domain: 0 - pi/2

This is the domain used to perform the computation.

Domain: >pi/2

The input value x has to be mapped to the computation domain 0 - pi/2. 
This can be shared by sin and cos.


When I ran the benchmark on my laptop (MacOS) FastMath was a fair bit 
faster for all scenarios. The actual computation is 5x faster when the 
value x is not in the correct domain. I was surprised by this so I added 
it to the JMH project to try on a few other machines. On an old linux 
workstation FastMath is about 3x faster. On a more modern workstation 
the difference is in favour of FastMath but only by about 1.2x.

In the event that the input is an edge case (NaN, Inf, or 0) then the 
java version is definitely faster everywhere I tested. This indicates 
that it may be better to check edge cases in java and then delegate to 
Math to do the computation, i.e. a hybrid approach. The edge cases for 
sin/cos are the same and so a SinCos implementation should have a speed 
gain for edge case numbers. This may not be relevant given that edge 
cases are likely to be rare in a real world usage scenario.

Given that Math.sin and Math.cos are native intrinsics in Java 8 they 
are running efficient code. Beating them will be hard to do with the 
same accuracy.

What requires further investigation is whether the reduction to the 
domain 0 - pi/2 done by FastMath is exact for all values of x, and if it 
is a significant part of the run-time of the function. If so then a 
hybrid sincos would be:

sinCos(double x, double[] result) {

   // Check edge cases and return if possible

   // Map to domain 0 - pi/2

   // Call Math.sin and Math.cos

   // map results to correct quadrant -pi to pi

   // return result

}

This would be simple to add to the current benchmark.

Alternatively if FastMath is accurate to 1 ULP as per Math then the 
entire set of routines could be ported from CM. So I have a bit more 
investigating to do on this to determine to determine the ULP range for 
FastMath compared to Math and the cost of mapping to the computation domain.

Alex

>
> Regards,
> Gilles
>
>> [...]
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>

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