Splitting done by Abdul Dakkak. Documentation of the process by Katie Poon.
The Mandelbrot set is a set of points in the complex plane. To determine which points lie inside the set we must iterate the recursive function $z_{n+1} = z_n^2 + c$ where c is the complex number we are testing and where we start iterating at $z_0 = 0$. If the magnitude of z stays constant, then the complex number c lies in the Mandelbrot set. Otherwise, the magnitude will blow up to infinity and not be in the set. The complex numbers on the plane will be colored according to whether it is in the set or not. The boundary of it forms a fractal.
If the point lies in the Mandelbrot set it is colored black. The coloring depends on the iteration. The points are colored according to which iteration the magnitude surpasses a constant and goes towards infinity. A different color corresponds to each iteration which creates the colorful border.
CUDA(Compute Unified Device Architecture) is a C programming language which addresses the CUDA chip and runs on the GPU (graphics processing unit). Developed by NVIDIA, the CUDA chip uses parallel programming to perform calculations simultaneously and quickly. The advantage of splitting a program would allow all the calculations to be done on the GPU and then send the information to other clients/computers which run on the CPU(central processing unit).
For a more detailed report of this process, read A Tale of Three Programs: CUDA to SZG, written by Chase Boren.
We will split the program, which runs on the CUDA, that generates the Mandelbrot set. The program allows us to magnify and move around the display window. Everytime you move or change the display, each point has to be recalculated by testing it in the recursive function and iterating. Since each point on the screen must be tested, it takes the CUDA's intense processing power to do this relatively quickly. By splitting the program, we will have the CUDA do the calculations and while other computers, which would not normally be able to run the program, display the output.
Using the Mandelbrot.cpp code as a template, we split the program into two sets of code, one with the information for the the CUDA, titled MandelbrotCUDA.cpp and the other for the client/viewer called MandelbrotOGL.cpp. MandelbrotCUDA.cpp contains the functions that calculate and the MandelbrotOGL.cpp has the drawing functions. We will use a standard C program and OpenGL to display the Mandelbrot set. Another implementation of the split is to use Mathematica as a viewer.
We are splitting between the server (GPU/calc) and the client(viewier/view)
There are three types of code:
Mandelbrot_gold.cpp
does not run on GPU
runs on GPU
does calculations
template for server and client
Here are some notes on what the different functions do within the code.
The split in the code occurs on pg. 5, after line 1, right after the # endif statement*
pg. 4
starting at line 12 #else is the code dealing with GPU.
the function CUDA_SAFE_CALL(line 18) checks for errors (debugging)
the function cudaGLMapBuferObject(line 18) puts gl_PBO into d_dst
PBO stands for pixel buffer object
GPU sends data to the NVIDIA card
the do statement on line 21 assigns color and computes the Mandelbrot set.
pg. 5
glTexSubImage2D function (line 3) supplies texture. It sends texture over a socket. It draws the Mandelbrot set.
texturing
patterns are large triangle with certain colors.
subtexture: use triangles smaller than a pixel so that each pixel has more than one colored triangle. the average color of the triangles in each pixel will be assigned to that pixel.
pg. 9-8
keyboard and mouse functions.
aliasing
functions are represented as sine waves of different frequencies.
information destroyer
different signals overlap and become indistinguishable when sampled.
high frequencies aren't represented accurately and can look like low frequencies when overlapped.
pixels around a line can only be apart of the line or not. If a line were to be drawn, the result would be a jagged staircase-like drawing, rather than a smooth line.
anti-aliasing
minimalizes blurriness and distortion caused by aliasing
subsampling- divide the pixel up and sample each subsection then average the subsamples
shade around lines so that it doesn't look choppy. Shading depends on how much of the line covers the subpixel.
We use the Mandelbrot.cpp code as a template and modify it to create the code for the CUDA.
Creation of Network Connection
A Network Functions section was added right before the Main Program section on pg. 9.
libraries taken from the FluidsGL program were added in this section
we opened connections and created a socket to accept connections from the port.
the server listens for the port number and the client sends information to the server at the port.
an infinite loop was created to accept requests from the client.
requests include: GETNEWFRAME and ZOOM
an if statement was added on pg. 9 right after the int main function under the Main Program section. If there isn't a port number the program will exit so it won't crash.
renamed the modified Mandelbrot.cpp code with Network Functions to MandelbrotCUDA.cpp. This code is meant for the GPU.
to access it go to *NVIDIA_CUDA_SDK/bin/linux/release/MandelbrotCUDA
We took the Mandelbrot.cpp code as a template and modified it for the viewer, naming it MandelbrotOGL.cpp.
any of the code that calculates or calls CUDA functions was commented out.
The display function on pg. 3-5 was commented out.
pg. 5, line 3: the glTexSubImage2D function draws the function so it is very important for the client's version of the program to have this.
go to NVIDIA_CUDA_SDK/projects/fluidsGL/fluidsClient.c* on the CUDA machine.
copy these libraries and add it to the Mandelbrot.OGL.cpp program
# include fcntl.h # include unistd # include netinet/in.h # include sys/socket.h # include arpa/inet.h
copy Network functions and paste right before the display function
this connects to the server and creates a socket
the getNewFrame function obtains data.
After debugging the two files (MandelbrotCUDA.cpp and MandelbrotOGL.cpp), the split is complete and we are able to view the Mandelbrot set on other computers. We tried it out on a Mac in the lab. The viewer in this case is a standard C program and OpenGL.
Using the diff2html generator, we can compare the codes from the split. Click the links below to view the side by side comparison. diff2html color coordinates the changes with green highlighted text representing modified lines, blue highlighted text as added lines, and red highlighted text as removed lines. It also has lists of the changed lines where you can click a line number and jump directly to that line in the code. diff2html is a useful and free tool to generate the diff file comparison utility in html.
Go to Abdul's week seven index to find the appropriate folders.
Save the MandelbrotDy-m7.tar.gz to the Desktop
Double click the file twice to get two folders, MandelbrotDy-m7 2 and MandelbrotDy-m7
First open a remote shell on the computer with the CUDA chip on it, namely ah130-15. To do it, open a terminal, which we'll call the CUDA terminal and type:
ssh cfgauss@ah130-15 (1) cd NVIDIA_CUDA_SDK/bin/linux/release (2) watch ./MandelbrotCUDA [port number] (3)
It will then ask for a password. Ask Professor Francis for it.
This takes us to the directory where the code is
Pick any number between $2^{10} + 1$ and $2^{16} - 1$ For example, 9093.
In a new terminal we'll call it the viewer terminal, type:
cd Desktop/ cd MandelbrotDy-m7 head MandelbrotOGL.cpp
This will give you the first few lines of the code which contain what to type in the command line to compile.
Copy the command line to compile on OSX listed below and compile.
g++ -framework OpenGL MandelbrotOGL.cpp -o MandelbrotOGL
Start the server from the viewer by typing:
./MandelbrotOGL [IP address] [Port number] (1)
Make sure this is the same port number as the one entered in the CUDA terminal
At this point the Mandelbrot set should be displayed in a window. To exit, hit apple-q on the mac keyboard.
To change the dimensions of the display window: - go to the viewer terminal and open the code in the vi editor. type: vi MandelbrotOGL.cpp
then scroll of the place that has the height and width and change accordingly. Keep in mind that the bigger the dimensions, the longer it will take CUDA to calculate, and the slower you can move around or zoom.
We can use Mathematica as a client to view the Mandelbrot set while the CUDA calculates the output. We used Mathlink, which is a programming language, to let Mathematica and the C program communicate.
Go to Abdul's week seven index to find the appropriate folders.
Save the mathlink-m7.tar.gz to the Desktop
Double click the file to extract the mathlink-m7 folder.
The server should be open between the viewer and the CUDA computer (ah-130-15) following the previous steps by opening a remote shell and connecting to the server. Mathematica takes the output from the CUDA machine.
In a new terminal type:
cd Desktop/ cd mathlink-m7 cd MandelbrotMathlink/ cp Makefile.mac Makefile make
Go to the mathlink-m7 on the Desktop. Open mandelbrotz.nb and follow the documentation within the Mathematica notebook. Everytime the viewer requests a new frame, the calculations are done on the CUDA machine and sent back for Mathematica to display.
You only need to extract the file once. Once it is on the computer, everytime you wish to start up CM1, just open a server using a remote shell so that it is connected to the CUDA and then find mandelbrotz.nb and open it.