Sunday, 29 September 2013

New term, C++11, Fractals and futures!

It's been a while, I really ought to get to updating this blog more often. It's the new trimester and the beginning of the final year at university though so I should have some interesting things in store for the coming months! The current modules I've been working on are Concurrency and Parallel Systems as well as Management of Software Projects, both have their ups and downs. Aside from that I have my honours project that I will be working over the next several months until April next year which will take up a big bulk of my time. Hopefully I will be able to make some interesting posts as I progress with that.

Anyways enough talk, first up we have a C++11 concurrency project that I've been working on over the past few days.

Mandelbrot Set

As a part of an exercise in understanding futures in the C++11 standard I parallelised the Mandelbrot set. The Mandelbrot set is famous for being used in the generation of the Mandelbrot fractal which can be seen in the image below.

Figure 1 - Mandelbrot Fractal
The generation of a fractal image such as the Mandelbrot above is commonly parallelised and is done so by simply splitting up the image into different section and then assigning the different work loads to different threads. By using std::async we are returned a std::future object instead of a std::thread. The std::future object will eventually hold the value being returned, in this case the pixel values of the image. [C++ Concurrency in Action Practical Multithreading]

int main()
{
 auto num_threads = thread::hardware_concurrency();

 // Calculate the range of pixels each thread will work on
 auto strip_height = dimension / num_threads;

 // Create futures for each thread
 vector<future<vector<float>>> futures;

 // We give each thread the calculation and the data range
 // with which we want it to work on. We also make it 
 // asynchronous so that we get a std::future reference back
 // so that we may retrieve the value we want later
 for(int i = 0; i < num_threads; ++i)
  futures.push_back(async(mandelbrotcalculation, 
     i * strip_height, 
     (i + 1) * strip_height));

 // The results of the calculation
 vector<vector<float>> results;
 // Get the results from the future! 
 // Bear in mind that f.get() can only be called once
 for (auto& f : futures)
  results.push_back(f.get());

 return 0;
}

The code above shows  the main for the application generating the fractals and how we would operate the futures for this mandelbrot generation. Bear in mind instead of creating std::thread objects we are using std::futures which allow us to get the returning value from the thread later. "Mandelbrotcalculation" is simply out function for calculating the colour for a single pixel, the maths of which will be covered in a later post. A more indepth discussion on how it works can be read here on Wolfram Mathworld.

The resulting application still takes some time and I still need to measure timings to see how much faster it is than just calculating everything on a single thread would be but results in the following image.

Figure 2 - Part of the Mandelbrot Rendered
Currently I still need to fix my application so that it renders the whole image rather than just a part but in the course of writing this blog post I have realised partially where I have gone wrong so I will have to get working on that asap.



Email : markmmiller@hotmail.co.uk
Xbox Live : Dr Death MK 2
Steam : 7thsanctum