julia - 使用 Plots.jl 高效地动画子图

标签 julia plots.jl

我正在尝试使用带有 GR 后端的 Plots.jl 在 Julia 中创建一个包含三个子图(一个表面,两个热图)的动画。到目前为止,我的代码中最慢的部分是这些图的生成,因此我试图找到最有效的方法来完成它。

我试过在动画循环中重新调用绘图,但这比原地修改要慢得多:

using Plots,Profile

function mcve(n)
    A = rand(n,100,100)
    B = rand(n,100,100)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        surface!(p[1],1:100,1:100,A[i,:,:])
        heatmap!(p[2],A[i,:,:])
        heatmap!(p[3],B[i,:,:])
    end
    gif(anim,"example.gif")
end

mcve(1)
@profile mcve(10)
Profile.print()

跟踪结果 https://pastebin.com/Lv9uCLE5

根据探查器,将近一半的运行时间花在调用 c 库的函数“setcharheight”上。有没有办法减少我需要调用它的次数?

最佳答案

我做了一些实验,发现有两件事可以显着加快绘图过程。

首先,我没有使用 surface!() 和 heatmap!() 重新绘制绘图,而是简单地替换了它们的 :z 系列。通过比较代码示例中的第一个函数与第三个函数以及第二个函数与第四个函数可以看出这一点。

二、GR.jl; setcharheight 非常慢。这可能是由于 ccall(),这意味着它可能取决于操作系统。通过将 xticks 和 yticks 设置为 false,可以实现显着的加速。这通过比较示例中的第一个到第二个和第三个到第四个函数来显示。

using Plots

function mcve(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        surface!(p[1],1:100,1:100,A[i,:,:])
        heatmap!(p[2],A[i,:,:])
        heatmap!(p[3],B[i,:,:])
    end
    gif(anim,"example1.gif")
end

function mcve4(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false,xticks=false,yticks=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false,xticks=false,yticks=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1,xticks=false,yticks=false)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        surface!(p[1],1:100,1:100,A[i,:,:],xticks=false,yticks=false)
        heatmap!(p[2],A[i,:,:],xticks=false,yticks=false)
        heatmap!(p[3],B[i,:,:],xticks=false,yticks=false)
    end
    gif(anim,"example4.gif")
end


function mcve2(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false,xticks =false,yticks= false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false,xticks = false,yticks= false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1,xticks = false,yticks= false)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        p[1][1][:z] = A[i,:,:]
        p[2][1][:z] = A[i,:,:]
        p[3][1][:z] = B[i,:,:]
    end
    gif(anim,"example2.gif")
end


function mcve3(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        p[1][1][:z] = A[i,:,:]
        p[2][1][:z] = A[i,:,:]
        p[3][1][:z] = B[i,:,:]
    end
    gif(anim,"example3.gif")
end

A = rand(1,100,100)
B = rand(1,100,100)

mcve(1,A,B)
mcve2(1,A,B)
mcve3(1,A,B)
mcve4(1,A,B)

A = rand(10,100,100)
B = rand(10,100,100)

println("Replot,ticks on")
@time mcve(10,A,B)
println("Replot,ticks off")
@time mcve4(10,A,B)
println(":z replace, ticks on")
@time mcve3(10,A,B)
println(":z replace, ticks off")
@time mcve2(10,A,B)

结果是

Replot,ticks on
 19.347849 seconds (12.78 M allocations: 399.848 MiB, 0.30% gc time)
Replot,ticks off
  6.227432 seconds (8.71 M allocations: 298.890 MiB, 0.88% gc time)
:z replace, ticks on
  8.572728 seconds (5.43 M allocations: 149.359 MiB, 0.24% gc time)
:z replace, ticks off
  1.805316 seconds (1.36 M allocations: 48.450 MiB, 0.40% gc time)

关于julia - 使用 Plots.jl 高效地动画子图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55794068/

相关文章:

scikit-learn - 在 Julia 中定义冲突模块

julia - 如何用 Julia 绘制球体?

julia - 如何在 julia 语言中使用集合操作

julia - 在 Julia 中使用带引号的表达式和数组

julia - Julia/Plots 中的对数轴外观

julia - 在 Julia 数组中获得独特的、非冗余的组合?

julia - 在 Julia 中动画化 ODE 的解决方案

julia - Plots.jl 和多边箱线图

julia - 从包含数据类型 UInt8 的数组中绘制图像

julia - 忽略 Plots.jl 中对数刻度上的零