On the last day of May I wrote about how to calculate prime numbers with LINQ in C#. To close that post I said that I’d use the PrimeNumbers delegate to evaluate PLINQ (Parallel LINQ) and measure the performance gains when the same calculation is done in parallel instead of in a sequential fashion.
As promised, today I show the performance gains when the same delegate is run in 2 cores (parallel) instead of only 1 core (sequential).
Here’s the delegate code:
Func<int, IEnumerable<int>> PrimeNumbers = max => from i in Enumerable.Range(2, max - 1) where Enumerable.Range(2, i - 2).All(j => i % j != 0) select i;
To make it a candidate to parallelization we must just call the AsParallel() extension method on the data to enable parallelization for the query:
Func<int, IEnumerable<int>> PrimeNumbers = max => from i in Enumerable.Range(2, max - 1).AsParallel() where Enumerable.Range(2, i - 2).All(j => i % j != 0) select i;
I set up a simple test to measure the time elapsed when using the two possible ways of calling the delegate function, that is, sequentially in one core and parallelized in my two available cores (I have an Intel Pentium Dual Core E2180 @ 2.00 GHz / 2.00 GHz).
Let’s calculate the prime numbers that are less than 50000 sequentially and in parallel:
IEnumerable<int> result = PrimeNumbers(50000);
Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); foreach(int i in result) { Console.WriteLine(i); } stopWatch.Stop(); // Write time elapsed Console.WriteLine("Time elapsed: {0}", stopWatch.Elapsed);
Now the results:
1 core
Time elapsed: 00:00:06.0252929
2 cores
Time elapsed: 00:00:03.2988351
When running in parallel the result was great - almost half the time it took to run the app in a sequential fashion.
The whole work gets divided into two worker threads/tasks as shown in Figure 1:
Figure 1 - The Parallel Stacks window in Visual Studio 2010
You can see that each thread is responsible for a range of values (data is partitioned among available cores). Thread 1 is evaluating the value 32983 and Thread 3 is evaluating 33073. This all occurs synchronously.
If I had a computer with 4 cores, the work would be divided into 4 threads/tasks and so on. If the time kept decreasing I’d achieve 1.5 seconds to run the app. Fantastic, isn’t it?
The new Microsoft Visual Studio 2010 (currently in Beta 2) comes with great debugging tooling for parallel applications as for example the Parallel Stacks shown in Figure 1 and the Parallel Tasks window shown in Figure 2:
Figure 2 - The Parallel Tasks window in Visual Studio 2010
This post gives you a rapid view of PLINQ and how it can leverage the power of you current and future hardware.
The future as foreseen by hardware industry specialists is a multicore future. So why not get ready to it right now? You certainly can with PLINQ. It abstracts all the low level code to get parallel and let’s you focus on what’s important: your business domain.
References
Features new to parallel debugging in VS 2010
Debugging Task-Based Parallel Applications in Visual Studio 2010 by Daniel Moth and Stephen Toub
Great lecture on what to expect from the multicore and parallel future…
Slides from Parallelism Tour by Stephen Toub
PLINQ documentation on MSDN
http://msdn.microsoft.com/en-us/library/dd460688%28VS.100%29.aspx
Parallel Computing Center on MSDN
http://msdn.microsoft.com/en-us/concurrency/default.aspx
Daniel Moth’s blog
http://www.danielmoth.com/Blog/index.htm
Microsoft Visual Studio 2010
http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx







A computer engineer that loves software engineering.