mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8214761: Bug in parallel Kahan summation implementation
Reviewed-by: darcy
This commit is contained in:
parent
7fff22afe7
commit
dd871819a0
5 changed files with 235 additions and 10 deletions
|
@ -156,7 +156,9 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
|
|||
count += other.count;
|
||||
simpleSum += other.simpleSum;
|
||||
sumWithCompensation(other.sum);
|
||||
sumWithCompensation(other.sumCompensation);
|
||||
|
||||
// Subtract compensation bits
|
||||
sumWithCompensation(-other.sumCompensation);
|
||||
min = Math.min(min, other.min);
|
||||
max = Math.max(max, other.max);
|
||||
}
|
||||
|
@ -241,7 +243,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
|
|||
*/
|
||||
public final double getSum() {
|
||||
// Better error bounds to add both terms as the final sum
|
||||
double tmp = sum + sumCompensation;
|
||||
double tmp = sum - sumCompensation;
|
||||
if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
|
||||
// If the compensated sum is spuriously NaN from
|
||||
// accumulating one or more same-signed infinite values,
|
||||
|
|
|
@ -734,7 +734,8 @@ public final class Collectors {
|
|||
a[2] += val;},
|
||||
(a, b) -> { sumWithCompensation(a, b[0]);
|
||||
a[2] += b[2];
|
||||
return sumWithCompensation(a, b[1]); },
|
||||
// Subtract compensation bits
|
||||
return sumWithCompensation(a, -b[1]); },
|
||||
a -> computeFinalSum(a),
|
||||
CH_NOID);
|
||||
}
|
||||
|
@ -765,8 +766,8 @@ public final class Collectors {
|
|||
* correctly-signed infinity stored in the simple sum.
|
||||
*/
|
||||
static double computeFinalSum(double[] summands) {
|
||||
// Better error bounds to add both terms as the final sum
|
||||
double tmp = summands[0] + summands[1];
|
||||
// Final sum with better error bounds subtract second summand as it is negated
|
||||
double tmp = summands[0] - summands[1];
|
||||
double simpleSum = summands[summands.length - 1];
|
||||
if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
|
||||
return simpleSum;
|
||||
|
@ -840,13 +841,19 @@ public final class Collectors {
|
|||
/*
|
||||
* In the arrays allocated for the collect operation, index 0
|
||||
* holds the high-order bits of the running sum, index 1 holds
|
||||
* the low-order bits of the sum computed via compensated
|
||||
* the negated low-order bits of the sum computed via compensated
|
||||
* summation, and index 2 holds the number of values seen.
|
||||
*/
|
||||
return new CollectorImpl<>(
|
||||
() -> new double[4],
|
||||
(a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
|
||||
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
|
||||
(a, b) -> {
|
||||
sumWithCompensation(a, b[0]);
|
||||
// Subtract compensation bits
|
||||
sumWithCompensation(a, -b[1]);
|
||||
a[2] += b[2]; a[3] += b[3];
|
||||
return a;
|
||||
},
|
||||
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
|
||||
CH_NOID);
|
||||
}
|
||||
|
|
|
@ -442,7 +442,7 @@ abstract class DoublePipeline<E_IN>
|
|||
/*
|
||||
* In the arrays allocated for the collect operation, index 0
|
||||
* holds the high-order bits of the running sum, index 1 holds
|
||||
* the low-order bits of the sum computed via compensated
|
||||
* the negated low-order bits of the sum computed via compensated
|
||||
* summation, and index 2 holds the simple sum used to compute
|
||||
* the proper result if the stream contains infinite values of
|
||||
* the same sign.
|
||||
|
@ -454,7 +454,8 @@ abstract class DoublePipeline<E_IN>
|
|||
},
|
||||
(ll, rr) -> {
|
||||
Collectors.sumWithCompensation(ll, rr[0]);
|
||||
Collectors.sumWithCompensation(ll, rr[1]);
|
||||
// Subtract compensation bits
|
||||
Collectors.sumWithCompensation(ll, -rr[1]);
|
||||
ll[2] += rr[2];
|
||||
});
|
||||
|
||||
|
@ -497,7 +498,8 @@ abstract class DoublePipeline<E_IN>
|
|||
},
|
||||
(ll, rr) -> {
|
||||
Collectors.sumWithCompensation(ll, rr[0]);
|
||||
Collectors.sumWithCompensation(ll, rr[1]);
|
||||
// Subtract compensation bits
|
||||
Collectors.sumWithCompensation(ll, -rr[1]);
|
||||
ll[2] += rr[2];
|
||||
ll[3] += rr[3];
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue