使用Plots.jl有效地动画子图

问题描述 投票:0回答:1

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

我已经尝试重新调用animate循环中的绘图,但这比在原地修改要慢得多:

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

根据分析器,几乎一半的运行时间花在一个函数“setcharheight”上,它正在调用一个c库。有没有办法减少我需要做的调用次数?

julia plots.jl
1个回答
2
投票

我做了一些实验,我发现了两件可以大大加快绘图过程的事情。

首先,我不是使用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)
© www.soinside.com 2019 - 2024. All rights reserved.