Using Parallel Extensions in LINQ

Posted by Filip Ekberg on March 25 2010 1 Comment

Once again, there was a little mistake in the last post I posted here which clearly didn’t effect the result that much. But it is still worth mentioning again. The ^ was not meant to be XOR, I was clearly thinking of Math.Pow.

In the last post I didn’t spend to much time talking about the Parallel Extensions for LINQ which are Really great and helpful; If you just love to replace traditional loops with LINQ-expressions you will probably find this post somewhat amusing.

So let’s dig down to the coding shall we!

First of all I have set up a smaller list with numbers, in this scenario we will just assume that we have a list of something and depending on the contents of that list, the time it takes to perform an action on that result, will differ. So here’s my list

var latency = new[] {1, 2, 4, 8};

Side note: new[]{} is really helpful, especially when you are creating examples like this!

And then I have a method that I want to run for each element in my list, which I will call PerformLogic

static int PerformLogic(int latency)
{
    var ms = 500 * latency;

    Thread.Sleep(ms);

    return ms;
}

In “traditional” programming, you would maybe do something like this:

for ( int i = 0; i < latency.Lenght; i++ )
{
    PerformAction(i);
}

But I don’t find that so amusing anymore, using LINQ is so much neater so instead of that for-loop we can actually do this:

(from i in latency select PerformAction(i)).ToList();

We don’t really have to write the expession like this though, since LINQ + .NET 4.0 is so smart, we can Refactor this to look somewhat like this:

(latency.Select(PerformLogic)).ToList();

The previous one is a bit more elaborate but this is fine aswell.

Making it parallel

We’ve reached the place where we no longer can refactor our code to make it faster, we can’t replace anything in the logic to make everything faster; We need to parallelize it!

Let’s have a look at what LINQ provides us with, oh, there’s an method called

.AsParallel

.

All I did now was changing the above code to this:

var result = (latency.Select(PerformLogic)).AsParallel().ToList();

And we have a parallelized query. For those with a fast mind can see that it will take about 7,5 seconds to run this since each of the “latency”-points will take itself times ½ second.

My final test-code looks like this

var latency = new[] {1, 2, 4, 8};

var start = DateTime.Now;

var result = (latency.Select(PerformLogic)).AsParallel().ToList();

var end = DateTime.Now;

Parallel.ForEach(result, Console.WriteLine);

Console.WriteLine("Execution time: {0}", (end - start));

And this is the output
LINQ Parallelism

Vote on HN

Using the Parallel Extensions in .NET 4.0 with C#

Posted by Filip Ekberg on March 24 2010 Leave a Comment

As .NET 4.0 will be released in a couple of weeks and the RC has been out for a while. It’s about time that I write something about the new helpful features of .NET 4.0. One of these helpful things are the Parallel Extensions and Parallel helpers that allowes you to do parallel programming.

Parallel computing is a form of computation in which many calculations are carried out simultaneously

In this example I will be using a WebRequestPool which just helps me out a bit to carry on this example. You might think if it like this: You have different request types which takes different long to execute you might be doing some WebDAV uploading, Image Fetching and other Over-The-Web-Access which takes time. Instead of waiting for each request to stop, you might as well run them simultaneously.

internal delegate void WebRequest(int ms);

internal class WebRequestPool
{
    public List Requests { get; set; }
}

So to make it easy I just have a simple Delegate which will allow us to Run/Invoke our WebMethods which all takes some input parameter that will, in some way, make the requests take longer / shorter.

Inside of the WebRequest class all we have is a Requests Pool, a simple list of delegates.

To make the whole a little bit interesting we have three different types of Requests: Standard Request, Long Request and ExtremeRequest

static void StandardRequest(int ms)
{
    Thread.Sleep(ms);
}

static void LongRequest(int ms)
{
    Thread.Sleep(ms^2);
}

static void ExtremeRequest(int ms)
{
    Thread.Sleep(ms^10);
}

So now we have three different types of methods that all validate with our delegate! Let’s head on and fire up this pool

var pool = new WebRequestPool
{
    Requests =
        new List
        {
            StandardRequest,
            LongRequest,
            ExtremeRequest,
            StandardRequest,
            LongRequest,
            ExtremeRequest
        }
};

This actually demonstrates something new too, the object initializers. So the list now contains six requests, All we want to do now is Processes these.

First of all we want to do it like we did in the old days, so I’ve created a method called ProcessPool which looks like this

private static void ProcessPool(WebRequestPool pool)
{
    var start = DateTime.Now;

    foreach (var item in pool.Requests)
        item.Invoke(2000);

    var end = DateTime.Now;

    var span = end - start;

    Console.WriteLine(
    string.Format("Execution time: {0}", span));
}

Of we run this the output is
Execution time

Now, that’s a bit too slow for me, so Let’s Parallelize that! All i’ve done now is to creat a new method called ProcessPoolAsParallel which takes the same input and expects to give the same result. There’s a little bit difference though, the foreach is now replaced with the

Parallel.ForEach

method.

private static void ProcessPoolAsParallel(WebRequestPool pool)
{

    var start = DateTime.Now;

    Parallel.ForEach(pool.Requests,
        item => item.Invoke(2000));

    var end = DateTime.Now;

    var span = end - start;

    Console.WriteLine(
        string.Format("Execution time: {0}", span));
}

So if we run this now the result is:
Parallel run 2

So this increased significally!

This is just a small example of the power in using Parallel programming patterns. Look into the Task class to head on!

Edit

There’s a slightly miss-used method in the code above, the ^ in C# is XOR and I was thinking of the Math.Pow, however, this doesn’t really matter in this case since the result is still Parallel = Faster.

Vote on HN