赢家?一些初步测试
以下是我对 aggdraw 渲染速度更快的输入类型的初步测试结果。在 aggdraw 文档中可以找到一条线索,它说 aggdraw.polygon() 只接受“序列”:正式定义为“str、unicode、list、tuple、bytearray、buffer、xrange”(http://docs. python.org/2/library/stdtypes.html)。幸运的是,我发现 aggdraw 渲染还接受其他输入类型。经过一些测试,我想出了一个输入容器类型的列表,我可以找到 aggdraw(也许还有 PIL)渲染支持:
不幸的是,aggdraw 不支持并在提供包含在以下内容中的坐标时导致错误:
然后进行性能测试!测试多边形是来自全球次国家省边界的全球行政单位数据库的 20 000 个(多)多边形的子集,使用 PyShp shapefile 读取器模块(http://code.google.com/p/pyshp )加载到内存中/)。为了确保测试只测量 aggdraw 的内部渲染速度,我确保仅在多边形坐标已经转换为 aggdraw 图像像素坐标之后,并且在我创建了具有正确输入类型和 aggdraw 的输入参数列表之后才启动计时器。笔和 .Brush 对象。然后我使用带有预加载坐标和参数的 itertools.starmap 计时并运行渲染:
t=time.time()
iterat = itertools.starmap(draw.polygon, args) #draw is the aggdraw.Draw() object
for runfunc in iterat: #iterating through the itertools generator consumes and runs it
pass
print time.time()-t
我的发现证实了元组和数组是最快的 Python 迭代器的传统观念,它们最终都是最快的。列表慢了大约 50%,numpy 数组也是如此(考虑到 Numpy 数组的速度声誉,这最初是令人惊讶的,但后来我读到 Numpy 数组只有在使用内部 Numpy 函数时才快,并且对于正常的 Python 迭代,它们通常比其他类型慢)。双端队列,通常被认为是快的,结果却是最慢的(几乎 100%,即慢 2 倍)。
### Coordinates as FLOATS
### Pure rendering time (seconds) for 20 000 polygons from the GADM dataset
tuples
8.90130587328
arrays
9.03419164657
lists
13.424952522
numpy
13.1880489246
deque
16.8887938784
换句话说,如果您通常将列表用于 aggdraw 坐标,您应该知道通过将它们放入元组或数组中可以获得 50% 的性能提升。不是最彻底的改进,但仍然有用且易于实施。
可是等等!我确实找到了另一种从 aggdraw 模块中榨取更多性能的方法——实际上相当多。我忘记了为什么这样做,但是当我尝试在渲染它们之前将转换后的浮点坐标四舍五入到最接近的像素整数作为整数类型(即“int(round(eachcoordinate))”)时,我得到了 6.5 倍的渲染加速(650%)与最常见的列表容器相比——非常值得且易于优化。令人惊讶的是,当渲染器不必担心舍入数字时,数组容器类型比元组快约 25%。这种预舍入不会丢失我可以看到的视觉细节,因为这些浮点无论如何只能分配给一个像素,这可能是为什么在将坐标发送到 aggdraw 渲染器之前对坐标进行预转换/预舍入加快了进程 bc 而 aggdraw 不必这样做的原因。一个潜在的警告是,删除十进制信息可能会改变 aggdraw 进行抗锯齿的方式,但在我看来,最终的地图仍然看起来同样抗锯齿和平滑。最后,必须权衡这种舍入优化与在 Python 中舍入数字所需的时间,但据我所知,进行预舍入所需的时间并没有超过渲染加速的好处。应该进一步优化如何以快速的方式对坐标进行四舍五入和转换。一个潜在的警告是,删除十进制信息可能会改变 aggdraw 进行抗锯齿的方式,但在我看来,最终的地图仍然看起来同样抗锯齿和平滑。最后,必须权衡这种舍入优化与在 Python 中舍入数字所需的时间,但据我所知,进行预舍入所需的时间并没有超过渲染加速的好处。应该进一步优化如何以快速的方式对坐标进行四舍五入和转换。一个潜在的警告是,删除十进制信息可能会改变 aggdraw 进行抗锯齿的方式,但在我看来,最终的地图仍然看起来同样抗锯齿和平滑。最后,必须权衡这种舍入优化与在 Python 中舍入数字所需的时间,但据我所知,进行预舍入所需的时间并没有超过渲染加速的好处。应该进一步优化如何以快速的方式对坐标进行四舍五入和转换。
### Coordinates as INTEGERS (rounded to pixels)
### Pure rendering time (seconds) for 20 000 polygons from the GADM dataset
arrays
1.40970077294
tuples
2.19892537074
lists
6.70839555276
numpy
6.47806400659
deque
7.57472232757
总而言之:数组和元组是提供绘图坐标的 aggdraw(可能还有 PIL?)时使用的最快的容器类型。
考虑到在 aggdraw 中使用正确的输入类型时可以获得很高的渲染速度,为地图渲染过程的其他方面(例如坐标转换例程)找到即使是最轻微的优化也变得尤为重要和有益(我已经在探索和例如,发现 Numpy 对于此类目的特别快)。
所有这一切的一个更普遍的发现是 Python 可以潜在地用于非常快速的地图渲染应用程序,从而进一步打开 Python 地理空间脚本的可能性;例如,理论上可以在大约 1.5*10=15 秒内渲染 200 000 多个省份的整个 GADM 数据集,而无需考虑坐标到图像的坐标转换,这比 QGIS 甚至 ArcGIS 快得多,根据我的经验,它在显示 GADM 数据集方面遇到了困难.
所有结果都是在 8 核处理器、2 年前的 Windows 7 机器上使用 Python 2.6.5 获得的。在加载和/或处理数据时,这些结果是否也是最有效的,这是一个必须在另一篇文章中测试和回答的问题。听听其他人是否已经对这些方面有任何好的见解会很有趣。