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

Le mar. 14 janv. 2020 à 12:24, <aherb...@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-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