matplotlib Animation.保存到动画 gif 非常慢

Ome*_*man 7 python imagemagick matplotlib animated-gif

我正在对在 IPython 3.1 笔记本中模拟的收敛过程进行动画处理。我在 matplotlib 动画中可视化散点图结果,并通过 ImageMagick 将其写入动画 gif。有 3000 帧,每帧大约有 5000 个点。

我不确定 matplotlib 到底是如何创建这些动画文件的,但它似乎缓存了一堆帧,然后将它们全部写出来——当我查看 CPU 使用率时,它一开始由 python 主导,然后由最后转换。

写出 gif 的速度非常慢。在现代 MacBook Pro 上将 70MB 文件写入 SSD 需要一个多小时。“转换”相当于 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);
Run Code Online (Sandbox Code Playgroud)

知道瓶颈可能是什么或者我如何加快速度吗?与模拟时间相比,我希望写出时间短一些。

版本: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报告:转换-大小432x720-深度8-延迟3.3333333333333335-循环0rgba:-文件/电容/SpherePlateAnimation.gif

Mar*_*ell 5

更新

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

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

which convert    # result may be "/usr/local/bin/convert"
Run Code Online (Sandbox Code Playgroud)

然后转到包含目录,例如

cd /usr/local/bin
Run Code Online (Sandbox Code Playgroud)

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

mv convert convert.real
Run Code Online (Sandbox Code Playgroud)

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

#!/bin/bash
dd bs=128k > $HOME/plot.rgba 2> /dev/null
Run Code Online (Sandbox Code Playgroud)

并通过执行以下操作使其可执行

chmod +x convert
Run Code Online (Sandbox Code Playgroud)

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

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

convert.real -limit memory 10000000 -size 432x720 -depth 8 -delay 3.33 -loop 0  $HOME/plot.rgba Files/Capacitance/SpherePlateAnimation.gif
Run Code Online (Sandbox Code Playgroud)

您还可以考虑将文件分成 2 个(或 4 个),dd并行使用和处理这两半,然后将它们附加在一起,看看是否有帮助。询问您是否想研究该选项。

原答案

我在这里大声地说出来,希望它可以直接帮助你,或者让别人的大脑抓住这个问题......

从您共享的命令行看来,它matplotlib是直接写入stdinImageMagickconvert工具的 - 我可以从RGBA:-告诉我它正在发送 RGB 加 Alpha 透明度作为原始值的参数中看到stdin

这意味着我没有建议将任何中间文件放在 RAM 磁盘上,这就是我发表评论的地方......

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

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

现在,让我们看看该输入流,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
Run Code Online (Sandbox Code Playgroud)

由于您无法提高执行的命令行的内存限制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
Run Code Online (Sandbox Code Playgroud)

您也可以在文件中更改它policy.xml,但这会更复杂,因此请先尝试这种方式,然后询问您是否遇到困难!

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