Ontario - 1 year ago 49

C# Question

doing the following

`static object aggLock = new object();`

static long max = 10000000;

static void Main(string[] args)

{

double totalSumSeq = 0;

double totalSumLock = 0;

// Seq

for (int i = 0; i < max; i++)

{

double y = Math.Sqrt(i);

totalSumSeq += y;

}

...

}

returns the expected 21,081,849,486.4393.

Using

`// Parallel.For(from, to, init, body, finally);`

Parallel.For(0, max, () => 0.0, (i, pls, y) => // (LoopVariable, ParallelLoopState, ThreadLocalVariable)

{

y = Math.Sqrt(i);

return y;

},

partSum =>

{

lock (aggLock)

{

totalSumLock += partSum;

}

}

);

instead I get totally different values, like in race conditions. Why?

Thanks

Ontario

Answer Source

You should aggregate the partial sums into y:

```
Parallel.For(0, max, () => 0.0, (i, pls, y) =>
{
//y = Math.Sqrt(i);
y += Math.Sqrt(i); // += to fix it
return y;
}, ...
```

`y`

is initialized to 0.0 with `() => 0.0`

and it resurfaces at the end of a partition as `partSum`

. But you only used the last value of the partition.

An alternative using PLinq (but Range() won't accept `long`

for max) :

```
double plinqSum = Enumerable
.Range(0, (int) max)
.AsParallel()
.Sum(i => Math.Sqrt(i)); // or just .Sum(Math.Sqrt);
```

This `.AsParallel().Sum()`

bit is essentially what you're building with the `Parallel.For()`