Mandelbrot, Mojo, Numpy and Numba

I recently read an article about connecting Python to the new Mojo language:

Python Can Now Call Mojo

The article had some code examples, including code to plot the Mandelbrot set, comparing plain Python, Python with Numpy, and Mojo, and what particularly interested me was that the code with Numpy was about 4 times faster than plain Python, whereas I had found Numpy for this task was slower than Python, as reported here: Computing and plotting the Mandelbrot set in Excel …

I have now updated the matplot-mandelbrot spreadsheet to include revised Numpy code, based upon on the code at the link above, and found that the Numpy code went from up to about 2 times slower to 3-4 times faster.

The updated spreadsheet and Python code can be downloaded from: FastMandelbrot.zip

The Numba code using Guvectorize remains by far the fastest, but the revised Python + Numpy code is now much faster than the plain Python. The original code loops through the results array cell by cell, converting the coordinates to a complex number then calling a plain Python routine to do the calculations:

def mandelbrot_set1(xmin,xmax,ymin,ymax,width,height,maxiter):
    r1 = np.linspace(xmin, xmax, width)
    r2 = np.linspace(ymin, ymax, height)
    n3 = np.empty((width,height))
    for i in range(width):
        for j in range(height):
            n3[i,j] = mandelbrot(r1[i] + 1j*r2[j],maxiter)
    res = (r1,r2,n3)
    return res

The revised code generates an array of complex numbers in a single operation, then generates the Mandelbrot values with a Numpy vectorized computation:

def mandelbrot8(x, y, maxiter, out = 0):
    """Generates a Mandelbrot set using NumPy for vectorized computation."""
    c = x[:, np.newaxis] + 1j * y[np.newaxis, :]
    z = np.zeros_like(c, dtype=np.complex128)
    image = np.zeros(c.shape, dtype=int)
    
    for n in range(maxiter):
        not_diverged = np.abs(z) <= 2
        image[not_diverged] = n
        z[not_diverged] = z[not_diverged]**2 + c[not_diverged]
        
    image[np.abs(z) <= 2] = maxiter
    return image  

The spreadsheet plots the calculated shape with chosen colour properties to full scale:

or scaled up by 100,000:

or 1,000,000:

or by 10,000,000:

or by 100,000,000:

and more, but after 1 billion, the image starts to lose resolution using 64 bit floats.

For those who want to go further, visit YouTube:

“The deepest Mandelbrot zoom ever! This zoom is over 24-hours long, uploaded to YouTube in 11 parts. It will finish on a mini-Mandelbrot. As such, I am claiming a world record for the deepest Mandelbrot video! I have kept to the traditional colouring style for this one. The first video may seem a little repetitive at first, but this builds more interesting shapes later into the zoom. You’re welcome to skip ahead a little. Consider playing your own music while you let this one roll. Sit back, relax, and soak it in. (The last minute also generates a cool optical illusion with the pattern it finishes on).”

This entry was posted in Arrays, Drawing, Excel, Link to Python, Maths, Newton, NumPy and SciPy, PyXLL, UDFs and tagged , , , , , , , . Bookmark the permalink.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.