Home | Resume | Blog Brian Ensink's Blog | Parallel Mandelbrot in C#

Parallel Mandelbrot in C#

by Brian Ensink 25. October 2008 17:25

mandelbrotMy last post was about the MSDN Magazine issue on parallelism.  For this post I wanted to show my first attempt at using the Task Parallel Library (TPL) with C#.  I wrote a very simple program to compute the Mandelbrot set.  This fractal is well known and there are plenty of resources online about it.

The first code fragment below shows the single threaded computation.  It loops over all the pixels in the image and calculates a value for each. Other code not shown lets the user input configuration settings and shows the resulting image.

To parallelize this code I used the Parallel.For() function for the outer loop.  This function from the TPL executes iterations of the loop in parallel and by design feels very similar to the ubiquitous for loop used by many languages. The second code fragment below shows the parallel version. As you can see very little has changed, just lines 4 and 14. This parallel function will scale not just to the 4 cores of my current PC (Q6600) but to almost any number of cores not available today.  In fact this parallel for loop iterates over the vertical columns of the image so it could potentially use as many cores as the horizontal resolution of the image.

   1: private void SingleThread()
   2: {
   3:     _results = new int[_settings.Width, _settings.Height];
   4:     for (int i = 0; i < _settings.Width; ++i)
   5:     {
   6:         double x = _settings.ProjectionWidth * ((double)i / (double)_settings.Width)
   7:              + _settings.Left;
   8:         for (int j = 0; j < _settings.Height; ++j)
   9:         {
  10:             double y = _settings.ProjectionHeight * ((double)j / (double)_settings.Height)
  11:                  + _settings.Bottom;
  12:             _results[i, j] = ComputePixel(x, y);
  13:         }
  14:     }
  15: }
 
   1: private void ParalellCalculate()
   2: {
   3:     _results = new int[_settings.Width, _settings.Height];
   4:     Parallel.For(0, _settings.Width, delegate(int i)
   5:     {
   6:         double x = _settings.ProjectionWidth * ((double)i / (double)_settings.Width) 
   7:             + _settings.Left;
   8:         for (int j = 0; j < _settings.Height; ++j)
   9:         {
  10:             double y = _settings.ProjectionHeight * ((double)j / (double)_settings.Height) 
  11:                 + _settings.Bottom;
  12:             _results[i, j] = ComputePixel(x, y);
  13:         }
  14:     });
  15: }

My anticipation for using the TPL for the first time grew while I wrote the single threaded version. Finally when the time came to call Parallel.For() it was very easy, almost disappointingly easy (a good thing!) and now I'm eager to try it out in more complicated scenarios. By the way the speedup I saw with the parallel version took the computation from about 5.5 seconds down to 1.5 seconds, approximately a 3.6x speedup.

The Task Parallel Library will be part of Visual Studio 2010 and .NET 4.0 and I look forward to using it in actual shipping code to real customers.

Tags:

Software Development

Comments are closed

About the author

I am currently a .NET developer and really enjoy the platform.  .NET seems to be able to take the developer whereever he/she wants to go.  To the desktop, to the web, to a database, etc.  At my day job I write desktop apps but I also like to toy with other tech as I have time.