Parallel.For quirk can leave your code running sequentially

! Warning: this post hasn't been updated in over three years and so may contain out of date information.

I have been experimenting with the Task Parallel Library December CTP in preparation for a talk at work, and in the process I came across a really weird feature that turns out to have a completely mundane solution. As it will likely catch others out too, I’ve decided to write a blog entry about it.

If you try taking the following C# code:

and convert it to use the new parallel for loop:

and run it on a computer with four cores, you might expect an output such as:

You will however be very disappointed with the result if you do, as the whole loop actually runs on one thread in a sequential fashion. It turns out that the reason for this is simple practicalities of getting this stuff working at a basic level for the CTP. As I discovered on the MSDN parallel forum, the reason is that the Parallel.For method breaks the loop up into groups of eight iterations and assigns each group of eight to the next available thread. So if your loop is of eight or less iterations, then it will run sequentially. You can test this by simply adjusting the for loop to 0 .. 15 say and it will use two threads if you have two cores etc.

6 thoughts on “Parallel.For quirk can leave your code running sequentially

  1. Is this a good thing? I don’t know very much about multi threading but I am trying to write a data parallel application and the difference between parallel and sequential code is very slight. I even have cases(processing image under 1 mb) when the non parallel code produces much better results then the parallel one. I am only trying to have my application process one half of the image by one processor and the other half bu the other processor. I think I would write my own code …

  2. Dreea,

    It is worth remembering that the library is only an early alpha test release and so it will likely improve by the time the release version comes out. However you have hit one of the problems with parallelism on the head: it’s hard and the simple solution is often very inefficient. It doesn’t therefore surprise me that your serial solution was faster than the parallel one.

    If your images are less than 1MB in size, perhaps processing two images at once, rather than two halves simultaneously, might give you speed increases?

  3. Dreea,

    a simple workaround which everyone will be using once they discover this:

    Parallel.For(0, 16, i =>
    {
    if (i%8==0) ProcessImage(i/8);
    });

  4. Well, I replace Parallel.For with Parallel.Do and it seems like a different thread is being used for each method call .
    As for the parallel processing time it’s better than the sequential time, but only after the parrallel.do/for are already called once(first time -> bad time, all the next times-> expected time). I guess this is due to a one-time start-up cost on first usage.
    Thanks for replies

  5. Dreea,

    Have you tried the June CTP yet? Does it make a difference to what you are doing? I haven’t tried it yet myself to see if there is a performance gain, so would be interested to know of others’ experiences.

Comments are closed.