LA.NET [EN]

Oct 08

Transforming loops in methods which invoke delegates

Posted in Multithreading      Comments Off on Transforming loops in methods which invoke delegates

In a previous post, we’ve started talking about data parallelism. Before getting started with the “real stuff”, I thought it would be a good idea to write a small post that explains how to break our loops into units of work. For instance, consider the following snippet:

int [] arr = {1, 2, 3};
for(var i = 0; i < arr.Length; i++){
    //do some work here
}

Before thinking about executing the loop in parallel, we need to identify the main units. It probably won’t take much time until you see that the work you’re doing will need to be wrapped inside an action. For instance, here’s a possible solution for creating a general for method which is capable of doing the same thing as the previous example:

void DoLoop(int startIndex, int endIndex, Action<int> loopBody)
{
    for (var i = startIndex; i < endIndex; i++)
    {
        loopBody(i);
    }
}

As you can see, we’ve introduced an Action delegate which “moved” the work you’re doing in the loop into a an Action which you can define. That means that now you’d use the following method for interacting over the elements in the array:

DoLoop(0, arr.Length,i => { /* do some work */});

In practice,this means that we can concentrate our multithreading efforts in the DoLoop method. The consumer of the method stays “ignorant” and will only have to worry with defining the Action that is executed (don’t forget to respect the assumptions presented in the previous post).

Things aren’t as straightforward when you don’t know the size of the collection. For instance, when you’re working with an IEnumerator, there’s no way for you to get the number of items without going through all the elements in the collection (and this is something which you might not really want to do in order to improve speed). One of the best approaches here is to build buffers of x items and handle them until you reach the end of the collection (we’ll leave this code for a future post).

Anyway, I digress. The main purpose of this post is completed! Now that we’ve identified the units of our loop, we can easily update the code of the DoLoop method so that it uses threads for doing its work. In the next post, we’ll start with the simplest approach there is: using the ThreadPool to add parallelism to our DoLoop method. Stay tuned!