## Ready, Set, Go!

## Getting Started with Numba

#### Requirements

Install the following dependencies using `pip3`

command:

`$ pip3 install numba Pillow`

`Tk`

comes pre-installed with Python and
`numpy`

is installed during the `numba`

installation in case it is not available.

#### Introduction

To get started with `numba`

, we will compute the Mandelbrot Set, a set of points on the complex plane
which always remain bounded by a threshold value while solving the quadratic recurrence equation.
It is an iterative problem which is also compute intensive and visual in nature.
This makes it a good starting point for new `numba`

users to witness the various ways
in which one can achieve code speed-up using `numba`

.

This Mandelbrot Set Generator is built using the `Tcl/Tk`

cross-platform UI framework
which comes pre-packaged with the python.
UI layer (which includes advanced feature such as Zooming) and computational layer are separated for better understanding.

Brief description of various parts of the code are provided below:

- Requisite libraries are imported along with the
`view_mandelbrot()`

function from`canvas.py`

(UI Layer) which is responsible for rendering the Mandelbrot Set. - The domain size is set as a 600x600 grid and the maximum number of iterations for each point on this grid is limited to 1000 (6000 for parallel codes).
`mandelbrot()`

function is used to evaluate the Mandelbrot Set. It returns the RBG color of each point on the grid (complex plane) as a nested list of tuples or a NumPy array.

Check out the video demo below:

#### Video Tutorial

#### Source Code

To get started with the exercise, simple clone the GitHub Repository

Each implementation has a dedicated file and the recommended learning sequence that should be followed is provided below:

File Name | Data Layer | Description | `parallel` Execution |
---|---|---|---|

01-python-list.py | `list` |
Pure Python implementation where a `list` of `list` of RBG tuples is used to store the computed RBG pixel values. |
- |

02-njit-python-list.py | `list` |
`@numba.njit` is applied on the pure Python implementation. |
- |

03-njit-parallel-python-list.py | `list` |
`@numba.njit` is applied on the pure Python implementation along with explicit `for` loop parallelization using `numba.prange()` . |
Yes |

04-numpy-array.py | NumPy array | Implementation where a 3-dimensional `numpy array` is used to store the computed RBG pixel values. |
- |

05-njit-numpy-array.py | NumPy array | `@numba.njit` is applied on the NumPy implementation. |
- |

06-njit-parallel-numpy-array.py | NumPy array | `@numba.njit` is applied on the NumPy implementation.
Numpy is primarily designed to be as fast as possible on a single core,
whereas numba automatically compiles a version which can run in parallel utilizing multiple threads if it contains reduction functions,
array math functions and many more functions or assignments or operations.
Explicit `for` loop parallelization is also performed using `numba.prange()` |
Yes |

07-numpy-vectorize.py | NumPy array | `@numpy.vectorize` creates a vectorized function which uses broadcasting rules insted of `for` loops.
Although users can write vectorized functions in Python, it is mostly for convenience and is neither optimal nor efficient. |
- |

08-numba-vectorize.py | NumPy array | `@numba.vectorize` creates a NumPy `ufunc` from a Python function as compared to writing C code if using the NumPy API.
A `ufunc` uses broadcasting rules insted of nested `for` loops. |
- |

09-parallel-numba-vectorize.py | NumPy array | `@numba.vectorize` also has the option to create a `ufunc` which executes in parallel. |
Yes |

To execute the code just run:

`$ python3 `*filename*.py

A Tkinter GUI will pop-up. You can use `left`

mouse button to drag and select an area to zoom into. `Right`

click to reset the canvas.