main – Program entry point
In main(), we create an instance of the mandelbrot class, apply a Mandelbrot calculation (execute) and validate results (verify). The constructor initializes the computation parameters with default values unless specified.
This is the function where the Mandelbrot calculation is called for each output point. The parallel_for_each invokes “num_of_tiles” tiles with “TILE_SIZE * TILE_SIZE” threads in each. In each tile, the (0, 0) th thread will determine which chunk of result this tile will calculate. Such synchronization across tiles is controlled using a temporary concurrency::array variable (count) which is incremented atomically. This also enables load balancing which is necessary because each point may take a different amount of time to compute. All threads in a tile synchronize at a barrier before proceeding to the computation. After synchronizing, each thread will scale the coordinate of an output point and apply the Mandelbrot calculation by calling mandelbrot::mandelbrot_calc function.
Also observe that the parallel_for_each is not using member variables directly because that would involve marshaling the this pointer which is not allowed by one of the restrictions. Hence the member variables are copied to local variables and then used inside the kernel.
This is a restrict(amp, cpu) function which implements the core of escape time algorithm used in generating a representation of the Mandelbrot set. This function is called from the kernel in mandelbrot::execute method and from the mandelbrot::verify method.
This function validates the results computed on the GPU. Here the same input parameters are used to calculate the results on the CPU again. Finally, these results are compared to determine correctness.
Download the sample
Please download the attached sample project of the Mandelbrot code that we discussed here and run it on your hardware. Try to understand what the code does and learn from it. You will need, as always, Visual Studio 11.