matplotlib animation.save 到 gif 动画很慢

matplotlib animation.save to animated gif very slow

我正在制作我在 IPython 3.1 笔记本中模拟的收敛过程的动画。我在 matplotlib 动画中可视化散点图结果,我正在通过 ImageMagick 将其写成动画 gif。一共有3000帧,每帧5000点左右。

我不确定 matplotlib 是如何创建这些动画文件的,但它似乎缓存了一堆帧,然后将它们一起写出来——当我查看 CPU 用法时,它是开头由 python 支配,最后由 convert 支配。

写出 gif 的速度非常慢。在现代 MacBook Pro 上将 70MB 文件写入 SSD 需要一个多小时。 'convert' 相当于 4(8 个超线程)核心机器上一个核心的 90%。

写第一个 65MB 大约需要 15 分钟,写最后一个 5MB 需要 2 多个小时。

我认为接下来是代码中有趣的部分 -- 如果还有其他有用的东西,请告诉我。

def updateAnim(i,cg,scat,mags):
    if mags[i]==0: return scat,
    cg.convergeStep(mags[i])
    scat.set_offsets(cg._chrgs[::2,0:2])
    return scat,

fig=plt.figure(figsize=(6,10))
plt.axis('equal')
plt.xlim(-1.2,1.2);plt.ylim(-1,3)
c=np.where(co._chrgs[::2,3]>0,'blue','red')
scat=plt.scatter(co._chrgs[::2,0],co._chrgs[::2,1],s=4,color=c,marker='o',alpha=0.25);
ani=animation.FuncAnimation(fig,updateAnim,frames=mags.size,fargs=(co,scat,mags),blit=True);
ani.save('Files/Capacitance/SpherePlateAnimation.gif',writer='imagemagick',fps=30);

知道瓶颈是什么或者我可以如何加快它的速度吗?我希望写出时间比模拟时间短。

版本:ImageMagick 6.9.0-0 Q16 x86_64 2015-05-30 http://www.imagemagick.org 版权所有: 版权所有 (C) 1999-2014 ImageMagick Studio LLC 特点:DPC 模块 代表(内置):bzlib cairo djvu fftw fontconfig freetype gslib gvc jbig jng jp2 jpeg lcms lqr ltdl lzma openexr pangocairo png ps rsvg tiff webp wmf x xml zlib

ps -aef 报道: convert -size 432x720 -depth 8 -delay 3.3333333333333335 -loop 0 rgba:- Files/Capacitance/SpherePlateAnimation.gif

更新

在执行此更新中建议的任何操作之前,请先阅读下面的原始答案。

如果您想对此进行更深入的调试,您可以将 ImageMagick 部分分离出来并确定问题出在哪里。为此,我会像这样找到您的 ImageMagick convert 程序:

which convert    # result may be "/usr/local/bin/convert"

然后转到包含目录,例如

cd /usr/local/bin

现在将原始 convert 程序保存为 convert.real - 您以后随时可以通过反转下面的最后两个参数再次将其改回:

mv convert convert.real

现在,将以下文件保存为convert

#!/bin/bash
dd bs=128k > $HOME/plot.rgba 2> /dev/null

并通过

使该文件可执行
chmod +x convert

现在,当您再次 运行 matplotlib 时,它将执行上面的脚本而不是 ImageMagick,并且该脚本会将原始 RGBA 数据保存在您的登录目录中的一个名为 plot.rgba 的文件。然后这会告诉你两件事...首先你会看到 matplotlib 现在 运行 是否更快,因为不再有任何 ImageMagick 处理,其次你会看到文件大小是否像我一样大约 4GB猜测。

现在您可以使用 ImageMagick 处理文件 matplotlib 完成使用后,内存限制为 10GB:

convert.real -limit memory 10000000 -size 432x720 -depth 8 -delay 3.33 -loop 0  $HOME/plot.rgba Files/Capacitance/SpherePlateAnimation.gif

您也可以考虑将文件拆分为 2(或 4)份,使用 dd 并并行处理两半并将它们附加在一起以查看是否有帮助。问,如果你想调查那个选项。

原答案

我有点想大声说出来,希望它能直接帮助你,或者让别人的大脑慢慢理解问题...

从您分享的命令行看来,matplotlib 正在直接写入 ImageMagick 的 convert 工具的 stdin - 我可以从 RGBA:- 参数中看到这告诉我它正在发送 RGB 加上 Alpha 透明度作为 stdin.

上的原始值

这意味着没有我可以建议放在 RAM 磁盘上的中间文件,这正是我要发表评论的地方...

第二件事是,在发送原始像素数据时,每个像素都由 matplotlib 计算和发送,因此它与模拟中的 5,000 个点保持不变 - 所以没有点减少或优化点数

另一件需要注意的事情是您使用的是 ImageMagick 的 16 位量化版本(您的版本字符串中的 Q16)。这实际上使内存需求加倍,因此如果您可以轻松地为 8 位量子深度重新编译 ImageMagick,那可能会有所帮助。

现在,让我们看一下输入流,RGBA -depth 8 表示每像素 4 个字节,每帧 432x720 像素,或每帧 1.2MB。现在,您有 3,000 帧,因此最少需要 3.6GB,加上 75MB 的输出文件。我怀疑这刚刚超过 ImageMagick 的自然内存限制,这就是为什么它最后变慢的原因,所以我的建议是检查 ImageMagick 的内存限制并考虑将它们增加到 4GB-6GB 或更多,如果你有它。

检查内存和其他资源限制:

identify -list resource

Resource limits:
  Width: 214.7MP
  Height: 214.7MP
  Area: 4.295GP
  Memory: 2GiB    <---
  Map: 4GiB
  Disk: unlimited
  File: 192
  Thread: 1
  Throttle: 0
  Time: unlimited

由于您无法提高 matplotlib 执行的命令行的内存限制,您可以通过在启动 matplotlib 之前导出的环境变量来做到这一点,如下所示:

export MAGICK_MEMORY_LIMIT=4294967296

identify -list resource

Resource limits:
  Width: 214.7MP
  Height: 214.7MP
  Area: 4.295GP
  Memory: 4GiB    <---
  Map: 4GiB
  Disk: unlimited
  File: 192
  Thread: 1
  Throttle: 0
  Time: unlimited

你也可以在你的policy.xml文件中更改它,但是这比较复杂,所以请先尝试这种方式并询问你是否卡住了!

请传递对此的反馈,因为我可能会根据它是否有效提出其他建议。还请 运行 identify -list configure 编辑您的问题并将输出粘贴到那里。

provides a good explanation of what goes wrong, but exporting a higher memory limit did not work. I do actually recommend to change policy.xml instead, the only trick part is to find where it is saved on your system. This answer 列出了一些位置,但最有可能在

/etc/ImageMagick-6/policy.xml

打开它,然后编辑显示

的行
<policy domain="resource" name="memory" value="256MiB"/>

类似于

<policy domain="resource" name="memory" value="4GiB"/>

或超出未处理 gif 大小的任何限制。如果不是,convert 子进程将被杀死。