parallel processing - Is this PLINQ bug? -
why plinq output different sequential processing , parallel.for loop
i want add sum of square root of 10,000,000 numbers.. here code 3 cases:
sequential loop:
double sum = 0.0; for(int = 1;i<10000001;i++) sum += math.sqrt(i);
output of is: 21081852648.717
now using parallel.for loop:
object locker = new object(); double total ; parallel.for(1,10000001, ()=>0.0, (i,state,local)=> local+math.sqrt(i), (local)=> { lock(locker){ total += local; } } );
output of is: 21081852648.7199
now using plinq
double tot = parallelenumerable.range(1, 10000000) .sum(i => math.sqrt(i));
output of is: 21081852648.72
why there difference between plinq output , parallel.for , sequential loop?
i suspect it's because arithmetic doubles isn't associative. information potentially lost while summing values, , what information lost depend on order of operations.
here's example showing effect:
using system; class test { static void main() { double d1 = 0d; (int = 0; < 10000; i++) { d1 += 0.00000000000000001; } d1 += 1; console.writeline(d1); double d2 = 1d; (int = 0; < 10000; i++) { d2 += 0.00000000000000001; } console.writeline(d2); } }
in first case, can add small numbers lots of times until become big enough still relevant when added 1.
in second case, adding 0.00000000000000001 1 results in 1 there isn't enough information in double represent 1.00000000000000001 - final result still 1.
edit: i've thought of aspect confusing things. local variables, jit compiler able (and allowed to) use 80-bit fp registers, means arithmetic can performed less information loss. that's not case instance variables have 64-bit. in parallel.for case, total
variable instance variable in generated class because it's captured lambda expression. could change results - may depend on computer architecture, clr version etc.
Comments
Post a Comment