[ 
https://issues.apache.org/jira/browse/NUMBERS-204?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17760525#comment-17760525
 ] 

Alex Herbert commented on NUMBERS-204:
--------------------------------------

The change to use scaling for sub-normal numbers has a small impact on 
performance. I added the new method to the existing DoubleSplitPerformance JMH 
benchmark. This project now uses Java 9 as the source target and so the methods 
to compute the round-off can be compared to using Math.fma. Here are the 
methods:
||Method||Description||
|fma|Math.fma(x, y, -x * y)|
|productLow|The new product low method|
|productLow0|The previous product low method|
|productLowS|A variant that adjusts the upper limit for scaling down to allow 
all other cases to always use up scaling. This removes a branch condition to 
check for sub-normals.|
|productLowUnscaled|The same method without scaling|

All methods were run using 5000 random samples that did not require any 
scaling. This tests only the optimum execution path through the code which 
would be expected to be used for most input data. The baseline used was the 
computation of the standard product x * y. The normalised score is the 
additional time to compute the round-off. These normalised scores are shown 
relative to the productLowUnscaled method.
||JDK||Method||Score||Normalised||Relative||
|11|baseline|12572.80307|0| |
|11|fma|13983.62927|1410.8|0.115|
|11|productLowUnscaled|24857.83952|12285.0|1.000|
|11|productLow0|36158.50286|23585.7|1.920|
|11|productLow|38357.92072|25785.1|2.099|
|11|productLowS|40497.88538|27925.1|2.273|
|17|baseline|2746.395858|0| |
|17|fma|3174.937238|428.5|0.040|
|17|productLowUnscaled|13513.24827|10766.9|1.000|
|17|productLow0|17507.63828|14761.2|1.371|
|17|productLow|18775.91109|16029.5|1.489|
|17|productLowS|21525.55327|18779.2|1.744|
h2. Notes
 * Use of Math.fma is 10-20x faster than the basic software implementation 
(productLowUnscaled).
 * Always performing scaling (productLowS) is slower than using a branch 
condition to check if scaling is required
 * The new method with scaling of sub-normals is 8-9% slower than the previous 
version.
 * JDK 17 shows less performance penalty for the variations of scaling compared 
to the basic implementation than observed in JDK 11.

> Sum class may incorrectly sum products if their round-off is sub-normal
> -----------------------------------------------------------------------
>
>                 Key: NUMBERS-204
>                 URL: https://issues.apache.org/jira/browse/NUMBERS-204
>             Project: Commons Numbers
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.1
>            Reporter: Alex Herbert
>            Assignee: Alex Herbert
>            Priority: Trivial
>             Fix For: 1.2
>
>
> The Sum class can be used to compute a sum of products with extended 
> precision by computing the round-off component of each product and using that 
> in the sum.
> When the round-off is sub-normal this computation may be incorrect as 
> intermediate sub-normal numbers may lose significant bits.
> This test currently fails due to a 1 ULP rounding error in computing the 
> round-off. This is combined with the exact product to create an incorrect sum.
> {code:java}
> @ParameterizedTest
> @CsvSource({
>     // Round-off == 0.0
>     "-2.73551683292218E-154, -1.0861547555023299E-154",
>     // Round-off = 4.9E-324
>     "1.4134286753429383E-154, -4.1395762189346144E-154",
> })
> void testSumOfProduct_tiny(double x, double y) {
>     final Sum s = Sum.create();
>     s.addProduct(x, y);
>     Assertions.assertEquals(x * y, s.getAsDouble());
> }
> {code}
> The productLow method currently uses downscaling if the arguments are too 
> large for the computation. Applying upscaling to the arguments so the product 
> and its round-off are both normal numbers corrects this rounding error.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to