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

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Gilles Sadowski-2
Hi.

Le mar. 14 janv. 2020 à 12:24, <[hidden email]> 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: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

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

Alex Herbert

On 14/01/2020 12:14, Gilles Sadowski wrote:

> Hi.
>
> Le mar. 14 janv. 2020 à 12:24, <[hidden email]> 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: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]