所以最近我决定编写一个程序来使用乌龟绘制mandelbrot集,除了一件事之外,它的效果非常好;它很慢,而且随着它的吸引而减速。如果我没记错的话,它的绘制方式如下:
def drawpoint(x,y,colour):
t.color(colour)
t.setpos(x,y)
t.down()
t.forward(1)
t.up()
并且程序通常计算点(使用math
(特别是它的三角法)及其颜色,然后绘制它。
我无法解释为什么它如此缓慢,因为它并不是一组令人惊讶的计算。我很确定这与turtle
有关,我想知道是否:
a)通过在math
和turtle
之间移动来减慢Python速度
b)当你画更多的点时,乌龟会减速
c)完全没有其他东西
是否有这些,如果是这样,我怎样才能加快速度?
答案 0 :(得分:0)
由于你没有给 很慢 提供时钟值,我必须做出假设。 (我并不同意PM 2Ring认为turtle.py可能不是你最好的选择。)我写了一个mandelbrot程序,使用通用的海龟操作,花了将近一个小时来绘制下面的320 x 240图像。然而,通过一些海龟优化,我能够将其降低到一分钟以上。并且可能还有更好的空间(详见下文)。具体优化:
通过turtle.speed("fastest")
使用screen.tracer(0, 0)
和screen.update()
来完成大部分工作
画在屏幕外。在我的下面的代码中,我更新每个
图像的垂直切片,所以你可以看到它的进展但是
不要延迟绘制每个像素。
我发现标记我的像素比你的像素更有效率
forward(1)
方法。这不是直观的,因为冲压跟踪
邮票和一堆多边形操作,但它仍然
超时更好。这很多是因为它避免了笔的上下
操作
使用创建使乌龟不可见
turtle = Turtle(visible=False)
或更高版本通过turtle.hideturtle()
。
无需浪费时间为每个像素绘制龟本身。
关闭撤消。 (在冲压的情况下,您无法将其关闭
由于turtle.py中的错误,但是)一般情况下,如果你正在抽签而且
不打算撤消你,turtle.setundobuffer(None)
可以
关闭此功能,而不是将每个操作存储在缓冲区中。
与任何速度优化程序一样,避免在运行时执行任何操作
你可以提前做 - 如果需要,浪费大量空间。
避免在运行时做多余事情。在我的例子中
下面,我试着尽量减少设置颜色的时间
预先计算颜色值并避免turtle.color(...)
笔颜色已设置为正确的颜色。
from turtle import Turtle, Screen
COORDINATES = (-2.0, -1.0, 1.0, 1.0)
WIDTH, HEIGHT = 320, 240
colors = {i: ((i & 0b1111) << 4, (i & 0b111) << 5, (i & 0b11111) << 3) for i in range(2 ** 5)}
def mandelbrot(turtle, minimum_x, minimum_y, maximum_x, maximum_y, iterations, width, height):
step_x, step_y = (maximum_x - minimum_x) / width, (maximum_y - minimum_y) / height
real = minimum_x
current_color = 0
while real < maximum_x:
imaginary = minimum_y
while imaginary < maximum_y:
color = 0
c, z = complex(real, imaginary), 0j
for i in range(iterations):
if abs(z) >= 4.0:
color = i & 31
break
z = z * z + c
if color != current_color:
turtle.color(colors[color])
current_color = color
turtle.setpos(real, imaginary)
turtle.stamp()
imaginary += step_y
screen.update()
real += step_x
screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.setworldcoordinates(*COORDINATES)
screen.colormode(255)
screen.tracer(0, 0)
turtle = Turtle(visible=False)
turtle.speed("fastest")
turtle.setundobuffer(1) # unfortunately setundobuffer(None|0) broken for turtle.stamp()
turtle.begin_poly()
# Yes, this is an empty polygon but produces a dot -- I don't know if this works on all platforms
turtle.end_poly()
screen.register_shape("pixel", turtle.get_poly())
turtle.shape("pixel")
turtle.up()
mandelbrot(turtle, *COORDINATES, 31, WIDTH, HEIGHT)
screen.exitonclick()
正如您所指出的,一个尚未解决的问题是,它会随着抽奖而变慢。绘制上面图像的前2 / 3rds只需要15秒,最后三分之一需要一分钟。我试图找到一个原因但到目前为止没有任何结果。一个有趣的转折是最后5%的绘图速度备份。