How can I make this fractal render faster in Zelle graphics?

泄露秘密 提交于 2019-12-24 00:48:15

问题


This takes over an hour to render this mandelbrot set with only 100 iteration and has taken 10 hours with 10,000 iterations. Is there a way to make it faster:

from graphics import *

width = 700
height = 700
win = GraphWin("Mandelbrot",width,height)
spacing = 1
zoom = 0.1
xOffset = -0.171

yOffset = 0.61
win.setBackground('black')
for x in range(0,width,spacing):
    for y in range(1,height,spacing):
        a = ((x / width) * zoom) - xOffset
        b = ((y / height) * zoom) - yOffset

        pt = Point(x,y)


        n = 0
        ca = a
        cb = b
        while(n<10000):
            aa = a * a - b * b
            bb = 2 * a * b
            a = aa + ca
            b = bb + cb
            n+=1
            if(abs(a+b) > 2000):
                break
            if(n < 2000):
               pt.setFill('black')
            if(n>5000):
                pt.setFill('grey')
            if(n>1000):
                pt.setFill('white')

        pt.draw(win)

回答1:


The fastest way in likely with numpy. See "How To Quickly Compute The Mandelbrot Set In Python" for details on this approach.

For plain pure Python, use the native complex numbers to speed-up the loop. Also use the abs() function to quickly compute the magnitude of the complex number:

>>> def mandle(c, boundary=2.0, maxloops=10000):
        # https://en.wikipedia.org/wiki/Mandelbrot_set
        z = 0.0j
        for i in range(maxloops):
            z = z * z + c
            if abs(z) > boundary:
                break
        return i

>>> mandle(0.04 + 0.65j)
21
>>> mandle(0.04 + 0.66j)
16
>>> mandle(0.04 + 0.67j)
12

The rendering itself isn't likely to be the slow part of your program (the 10,000 loops can dwarf the time to plot a point). That said, if you want to speed the rendering, typically the only choice is to plot multiple points per call to the graphics library.

Lastly, consider whether you really want the maximum number of iterations to be 10,000. You can get good results with a maximum of 200 iterations.




回答2:


In addition to the complex numbers suggested by @RaymondHettinger, there are several things we can do Zelle-graphics-wise to speed things up. The first is to not use Point(), it has too much overhead. The win instance it self has a plot() method for bitmap manipulation that doesn't have the overhead of Point(), i.e. can't undraw it, can't move it.

The second is to turn off autoflush and do our own screen flushes on each column. Finally, simply avoid doing any computation you don't need to -- e.g. ca can be calculated in the outer loop, not the inner. The color can be calculated outside the innermost loop, etc.

Here's my rework as above -- timing a 70 x 70 image, it's about 7x faster than your original code:

from graphics import *

spacing = 1
zoom = 0.1

xOffset, yOffset = -0.171, 0.61

width, height = 700, 700

win = GraphWin('Mandelbrot', width, height, autoflush=False)

win.setBackground('black')

xzoom, yzoom = zoom / width, zoom / height

for real in range(0, width, spacing):

    ca = real * xzoom - xOffset

    for imaginary in range(0, height, spacing):

        c, z = complex(ca, imaginary * yzoom - yOffset), 0j

        n = 0

        while n < 10000:

            if abs(z) > 2000:
                break

            z = z * z + c

            n += 1

        color = 'black'

        if n > 5000:
            color = 'grey'
        elif n > 1000:
            color = 'white'

        if color != 'black':
            win.plot(real, imaginary, color=color)

    win.flush()

Not the full order of magnitude we might hope for, but seven hours less turn around time is still somthing!

Finally, there's a bug in your code that keeps pixels from ever coming out grey -- I've fixed that.



来源:https://stackoverflow.com/questions/43968828/how-can-i-make-this-fractal-render-faster-in-zelle-graphics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!