Multi-Threaded Mandelbrot Solver

This was an exercise in modifying a program to make it run in parallel. On a dual core system, the time spent processing was cut in half.

Test Machine:

Operating System:

Microsoft Windows XP Professional

System Model:

HP xw4400 Workstation

Processor (x2):

x86 Family 6 Model 15 Stepping 6 GenuineIntel ~2400 Mhz

The Results:

Processing time was measured using the clock() function from the ctime library. A measurement was taken immediately preceding the solve algorithm and immediately following, then the two were compared to calculate the actual processing time. Each method was tested in 20 separate trials. The average time for each is shown below. All trials were conducted with a frame size of 700 pixels X 500 pixels and compiler optimization disabled. Thanks to Chris Kaynor for providing the interface.

Serial:

0.408 seconds

Parallel:

0.204 seconds

The Code:

The following code snippet is the function that each thread executes upon creation. To download the entire source code, click here.

unsigned __stdcall
parallel_mandelbrot::my_thread_func(void *param)
{
	parallel_mandelbrot *my_value = (parallel_mandelbrot *) param;

	/* Loop indefinitely, until the poison pill is encountered.
	   The poison pill is implemented by a work item added to the
	   queue with a maximum iteration value of -1. */
	while(true){
		/* Be sure that only one thread may pull work from the queue at a time. */
		EnterCriticalSection(&my_value->lock);

		Parameters params;
		/* If there is work on the queue, retrieve the work item.
		   Otherwise, spin. */
		if(!my_value->tasks.empty())
			params = my_value->tasks.front();
		else{
			LeaveCriticalSection(&my_value->lock);
			continue;
		}

		/* Check to see if this is a poison pill. (If it is,
		   max_iters will = -1) If so, break out of the loop. */
		if (params.max_iters < 0){
			LeaveCriticalSection(&my_value->lock);
			break;
		}

		/* Now take the work item off of the queue. */
		my_value->tasks.pop();

		LeaveCriticalSection(&my_value->lock);

		/* Solve the work item. */
		my_value->solve_area(  params.x0, params.y0, params.x1, params.y1, params.max_iters );
	}

	return 0;
}