I am trying to create a simple demonstration of using 'parallel LINQ' (PLINQ). I have two versions of my task, in C#:
var result = Enumerable.Range(1,1000000).Where(x => IsPrime(x)).ToList();
var result = Enumerable.Range(1,1000000).AsParallel().Where(x => IsPrime(x)).ToList();
and use a System.Diagnostics.StopWatch
to time both versions. On my machine (4 Cores, 8 Logical Processors), the first takes approx. 114 seconds, while the PLINQ version takes approx. 30 seconds. I know enough not to expect an 8x improvement, though I imagined I'd get better than 3.8X, given the length, and the purity (no I/O) of the task.
But looking at the individual core utilizations using the Resource Monitor, I am surprised by what I see.
Before the task starts, the overall processor utilization is 5-10%. When the task is run, after a start-up spike I see:
With the first (LINQ) version, all eight cores get significantly busier than before starting the task, some busier than others, but with a very spiky pattern for each. The overall processor usage runs at a little under 30%.
With the second version (PLINQ) all eight processors run at near 100%, as does the overall processor usage.
The second scenario makes more sense to me, though I think I imagined I would see 7 cores running flat out evaluating the query and the eighth one doing all the other stuff.
For the first version, I had (naïvely) expected that I would see one core running flat out and the others (running various background processes) much less. Can someone explain how the distribution is being managed? And why - in a pure processing scenario like this - the gain from parallelism isn't greater?