mandel -x -0.5 -y 0 -s 2 | mandel -x -0.5 -y -0.5 -s 1 | mandel -x -0.5 -y -0.5 -s 0.25 |
Here is the source code for a simple program that generates images of the Mandelbrot set and saves them as BMP files. Just download all of the files and run make to build the code. If you run the program with no arguments, then it generates a default image and writes it to mandel.bmp. Use display mandel.bmp to see the output. You can see all of the command line options with mandel -h, and use them to override the defaults. (Each of the images on this page is labelled with the command that produces it.) This program uses the escape time algorithm. For each pixel in the image, it starts with the x and y position, and then computes a recurrence relation until it exceeds a fixed value or runs for max iterations.
int iterations_at_point( double x, double y, int max ) { double x0 = x; double y0 = y; int iter = 0; while( (x*x + y*y <= 4) && iter < max ) { double xt = x*x - y*y + x0; double yt = 2*x*y + y0; x = xt; y = yt; iter++; } return iter; }
Then, the pixel is assigned a color according to the number of iterations completed. An easy color scheme is to assign a gray value proportional to the number of iterations, but others are possible. Here are a few color variations of the same configuration:
mandel -x -.38 -y -.665 -s .05 -m 1000 | ||
The max value controls the amount of work done by the algorithm. If we increase max, then we can see much more detail in the set, but it may take much longer to compute. Generally speaking, you need to turn the max value higher as you zoom in. For example, here is the same area in the set computed with four different values of max:
mandel -x 0.286932 -y 0.014287 -s .0005 | |||
-m 50 | -m 100 | -m 500 | -m 1000 |
Obviously, generating all those frames will take some time. We can speed up the process significantly by using multiple processes simultaneously. To do this, make mandelmovie accept a single argument: the number of processes to run simultaneously. So, mandelmovie 3 should start three mandel processes at once, then wait for one to complete. As soon as one completes, start the next, and keep going until all the work is complete. mandelmovie should work correctly for any arbitrary number of processes given on the command line.
Modify mandel.c to use an arbitrary number of threads to compute the image. Each thread should compute a completely separate band of the image. For example, if you specify three threads and the image is 500 pixels high, then thread 0 should work on lines 0-165, thread 1 should work on lines 166-331, and thread 2 should work on lines 332-499. Add a new command line argument -n to allow the user to specify the number of threads. If -n is not given, assume a default of one thread. Your modified version of mandel should work correctly for any arbitrary number of threads and image configuration.
Note that each thread is going to work on a completely different subset of the data, so you do not have to worry about synchronization and race conditions. (That will be the next assignment.)
Double check that your modified mandel produces the same output as the original.
If your movie starts off zooming very slowly, and then accelerating to the end, try this: To get a nice smooth zoom from s=a to s=b, start with s=a and then multiply it each time by exp(log(b/a)/51).
mandel.c uses the standard getopt routine to process command line arguments. To add the -n argument, you will need to add n: to the third argument of getopt, add an additional case statement underneath, and update the help text.
Where main previously made one call to compute_image, you will need to modify it to create N threads with pthread_create, assign each to create one slice of the image, and then wait for each to complete with pthread_join.
pthread_create requires that each thread begin executing a function that only takes one pointer argument. Unfortunately, compute_image takes a whole bunch of arguments. What you will need to do is modify create_image from this:
void compute_image( struct bitmap *b, double xmin, double xmax, double ymin, double ymax, double itermax );to this:
void * compute_image( struct thread_args *args )where thread_args contains everything that you want to pass to compute_image. Now, for each thread, allocate a thread_args structure and pass it as the fourth argument to pthread_create, which will turn around and pass it to compute_image.
Pthreads requires compute_image to return a void *, but since it doesn't actually need to return any data, just return 0; at the end of the function.
This assignment is due at 11:59PM on Thursday, Feb 15th. Late assignments are not be accepted.
For this assignment, you may find it easier to (initially) work on your own laptop, in order to more easily work with the images generated. Leave extra time to ensure that your program works correctly when transferred to the CSE student machines, where it will be graded.
I will assemble a gallery of the submitted images, and the class will vote on the best one. The winner will receive five percent extra credit.
For up to ten percent extra credit, construct an interactive Mandelbrot browser that allows the user to explore by pointing and clicking, instead of typing in numbers. Use whatever language or toolkit you are most comfortable with.
(If you attempt more than one extra credit, the maximum total is ten percent extra credit.)