1
votes

How I can make my Python program faster? This program calculates the Mandelbrot set and draws it with turtle. I think the problem is in the for loop. Maybe the steps are taking too much time.

import numpy as np
import turtle
turtle.ht()
turtle.pu()
turtle.speed(0)
turtle.delay(0) turtle.colormode(255)

i= int(input("iteration = "))
g = int(input("accuracy  = "))
xmin = float(input("X-min: "))
xmax = float(input("X-max: "))
ymin = float(input("Y-min: "))
ymax = float(input("Y-max: "))
cmode = int(255/i)

input("PRESS TO START")
for x in np.arange(xmin,xmax,1/g):
    for y in np.arange(ymin,ymax,1/g):
        c = x + y * 1j
        z = 0
        t = 1
        for e in range(i):
            z = z * z + c
            if abs(z) > 3:
                turtle.setx(g*c.real)
                turtle.sety(g*c.imag)
                turtle.dot(2,e*cmode,e*cmode,e*cmode)
                t = 0

        if t == 1:
            turtle.setx(g*c.real)
            turtle.sety(g*c.imag)
            turtle.dot(2,"black")

input("Calculated!")
turtle.mainloop()

Here is an example

1
Questions regarding performance are more likely to be answered on the Code Review. - Badda
Thank you! I am a new user here so thanks for your help. Did not know that. @Badda - akinoioi
First speed-up would be to add break following t = 0 (if the draw routine is triggered, you don't need to continue calculations for this point). Beyond that, Python just isn't terribly fast; you could try to push the calculations into Numpy like thesamovar.wordpress.com/2009/03/22/… (claims a 3x speed-up) or you could switch to a faster compiled language like Julia julialang.org (even the name is appropriate ;-) and they include a 20x speed-up on mandelbrot set as one of their benchmarks) - Hugh Bothwell
Do you continue to iterate after the function value has escaped? - Weather Vane
... one more intermediate step before switching languages: you could try Cython cython.org which lets you compile (statically typed) Python directly to native code. - Hugh Bothwell

1 Answers

1
votes

The following rework should be a hundred times faster than your original:

import numpy as np
import turtle

i = int(input("iteration = "))
g = int(input("accuracy  = "))
xmin = float(input("X-min: "))
xmax = float(input("X-max: "))
ymin = float(input("Y-min: "))
ymax = float(input("Y-max: "))

cmode = int(255 / i)

input("PRESS TO START")

turtle.hideturtle()
turtle.penup()
turtle.speed('fastest')
turtle.colormode(255)
turtle.setundobuffer(None)  # turn off saving undo information

turtle.tracer(0, 0)

for x in np.arange(xmin, xmax, 1 / g):
    for y in np.arange(ymin, ymax, 1 / g):
        c = x + y * 1j
        z = 0
        t = True

        for e in range(i):
            z = z * z + c

            if abs(z) > 3.0:
                turtle.setposition(g * c.real, g * c.imag)
                rgb = e * cmode
                turtle.dot(2, rgb, rgb, rgb)
                t = False
                break

        if t:
            turtle.setposition(g * c.real, g * c.imag)
            turtle.dot(2, "black")

    turtle.update()

print("Calculated!")

turtle.mainloop()

The significant change is the use of the combination of tracer() and update() to avoid visually plotting every dot for the user and just drawing as each vertical column completes.