为什么用 Matplotlib 绘图这么慢? [英] why is plotting with Matplotlib so slow?

查看:76
本文介绍了为什么用 Matplotlib 绘图这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在评估不同的 Python 绘图库.现在我正在尝试 matplotlib 并且我对性能非常失望.下面的示例是从 SciPy 示例 修改而来的,并且每秒仅给我约 8 帧!

I'm currently evaluating different python plotting libraries. Right now I'm trying matplotlib and I'm quite disappointed with the performance. The following example is modified from SciPy examples and gives me only ~ 8 frames per second!

有什么方法可以加快速度还是我应该选择不同的绘图库?

Any ways of speeding this up or should I pick a different plotting library?

from pylab import *
import time

ion()
fig = figure()
ax1 = fig.add_subplot(611)
ax2 = fig.add_subplot(612)
ax3 = fig.add_subplot(613)
ax4 = fig.add_subplot(614)
ax5 = fig.add_subplot(615)
ax6 = fig.add_subplot(616)

x = arange(0,2*pi,0.01)
y = sin(x)
line1, = ax1.plot(x, y, 'r-')
line2, = ax2.plot(x, y, 'g-')
line3, = ax3.plot(x, y, 'y-')
line4, = ax4.plot(x, y, 'm-')
line5, = ax5.plot(x, y, 'k-')
line6, = ax6.plot(x, y, 'p-')

# turn off interactive plotting - speeds things up by 1 Frame / second
plt.ioff()


tstart = time.time()               # for profiling
for i in arange(1, 200):
    line1.set_ydata(sin(x+i/10.0))  # update the data
    line2.set_ydata(sin(2*x+i/10.0))
    line3.set_ydata(sin(3*x+i/10.0))
    line4.set_ydata(sin(4*x+i/10.0))
    line5.set_ydata(sin(5*x+i/10.0))
    line6.set_ydata(sin(6*x+i/10.0))
    draw()                         # redraw the canvas

print 'FPS:' , 200/(time.time()-tstart)

推荐答案

首先,(虽然这根本不会改变性能)考虑清理你的代码,类似于:

First off, (though this won't change the performance at all) consider cleaning up your code, similar to this:

import matplotlib.pyplot as plt
import numpy as np
import time

x = np.arange(0, 2*np.pi, 0.01)
y = np.sin(x)

fig, axes = plt.subplots(nrows=6)
styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
lines = [ax.plot(x, y, style)[0] for ax, style in zip(axes, styles)]

fig.show()

tstart = time.time()
for i in xrange(1, 20):
    for j, line in enumerate(lines, start=1):
        line.set_ydata(np.sin(j*x + i/10.0))
    fig.canvas.draw()

print 'FPS:' , 20/(time.time()-tstart)

在上面的例子中,我得到了大约 10fps.

With the above example, I get around 10fps.

只是一个简短的说明,根据您的具体用例,matplotlib 可能不是一个很好的选择.它面向出版质量的数字,而不是实时显示.

Just a quick note, depending on your exact use case, matplotlib may not be a great choice. It's oriented towards publication-quality figures, not real-time display.

但是,您可以做很多事情来加快此示例的速度.

However, there are a lot of things you can do to speed this example up.

之所以如此缓慢,主要有两个原因.

There are two main reasons why this is as slow as it is.

1) 调用 fig.canvas.draw() 重绘一切.这是你的瓶颈.在您的情况下,您不需要重新绘制坐标区边界、刻度标签等内容.

1) Calling fig.canvas.draw() redraws everything. It's your bottleneck. In your case, you don't need to re-draw things like the axes boundaries, tick labels, etc.

2) 在你的情况下,有很多带有很多刻度标签的子图.这些需要很长时间才能绘制.

2) In your case, there are a lot of subplots with a lot of tick labels. These take a long time to draw.

这两个都可以通过使用 blitting 来修复.

Both these can be fixed by using blitting.

要有效地进行 blitting,您必须使用后端特定的代码.在实践中,如果你真的很担心流畅的动画,你通常会在某种 gui 工具包中嵌入 matplotlib 图,不管怎样,所以这不是什么大问题.

To do blitting efficiently, you'll have to use backend-specific code. In practice, if you're really worried about smooth animations, you're usually embedding matplotlib plots in some sort of gui toolkit, anyway, so this isn't much of an issue.

但是,在不了解您在做什么的情况下,我无法帮助您.

However, without knowing a bit more about what you're doing, I can't help you there.

尽管如此,有一种 gui-neutral 的方法仍然相当快.

Nonetheless, there is a gui-neutral way of doing it that is still reasonably fast.

import matplotlib.pyplot as plt
import numpy as np
import time

x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)

fig, axes = plt.subplots(nrows=6)

fig.show()

# We need to draw the canvas before we start animating...
fig.canvas.draw()

styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
def plot(ax, style):
    return ax.plot(x, y, style, animated=True)[0]
lines = [plot(ax, style) for ax, style in zip(axes, styles)]

# Let's capture the background of the figure
backgrounds = [fig.canvas.copy_from_bbox(ax.bbox) for ax in axes]

tstart = time.time()
for i in xrange(1, 2000):
    items = enumerate(zip(lines, axes, backgrounds), start=1)
    for j, (line, ax, background) in items:
        fig.canvas.restore_region(background)
        line.set_ydata(np.sin(j*x + i/10.0))
        ax.draw_artist(line)
        fig.canvas.blit(ax.bbox)

print 'FPS:' , 2000/(time.time()-tstart)

这给了我大约 200fps.

This gives me ~200fps.

为了让这更方便一些,在最新版本的 matplotlib 中有一个 animations 模块.

To make this a bit more convenient, there's an animations module in recent versions of matplotlib.

举个例子:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)

fig, axes = plt.subplots(nrows=6)

styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
def plot(ax, style):
    return ax.plot(x, y, style, animated=True)[0]
lines = [plot(ax, style) for ax, style in zip(axes, styles)]

def animate(i):
    for j, line in enumerate(lines, start=1):
        line.set_ydata(np.sin(j*x + i/10.0))
    return lines

# We'd normally specify a reasonable "interval" here...
ani = animation.FuncAnimation(fig, animate, xrange(1, 200), 
                              interval=0, blit=True)
plt.show()

这篇关于为什么用 Matplotlib 绘图这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆