Как ускорить очень медленный анимационный сюжет в MATLAB

Я пытаюсь создать анимированный сюжет, но мой код очень медленный, возможно, метод, который я использую, слишком наивен. В приведенном ниже примере у меня есть 4 субплота по 3 строки, которые я обновляю в цикле "время".

clc;clear;close all;
state = {'$x-Position$','$x-Velocity$','$y-Position$','$y-Velocity$'};
ylabels = {'$x$','$\dot{x}$','$y$','$\dot{y}$'};
options1 = {'interpreter','latex'};
options2 = {'interpreter','latex','fontsize',20};
maxT = 300;

for pp = 1:4
    hh1(pp)=subplot(2,2,pp);
    xlabel('$t$',options2{:});
    ylabel(ylabels{pp},options2{:});
    title(state{pp},options1{:})
    xlim([0 maxT])
    hold on
end
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
for k = 2:maxT
    for p = 1:4
        plot(hh1(p),k-1:k,x(p,k-1:k),'b','linewidth',2)
        plot(hh1(p),k-1:k,z(p,k-1:k),'m')
        plot(hh1(p),k-1:k,x_est(p,k-1:k),':k','linewidth',2)
    end
    drawnow;
end

Как видно из вывода профилировщика, drawnow убивает время. Есть ли способ, как я могу быть более эффективным в создании этой анимации?

1 ответ

Поскольку вы хотите анимацию, нет альтернативы использованию drawnow обновить кадр. Тем не менее, это не drawnow в частности, который замедляет вас - профилировщик может вводить в заблуждение... drawnow просто обновляет все графические изменения с момента последней перерисовки, что в вашем случае представляет собой десяток новых сюжетов!

Вы найдете это hold довольно медленно Например, если вы мудрее о своем холдинге, удалите существующий hold on и удерживать только при фактическом построении

% ... above code the same but without 'hold on'
for p = 1:4
    hold(hh1(p), 'on');
    % plots
    hold(hh1(p), 'off');
end

Это экономит ~10% времени на моем ПК (12, 3 с до 11, 3 с).


Реальное ускорение происходит от удаления hold целиком, вместе со всеми plot звонки! Этот метод также не затрагивает форматирование строки, которое поможет со скоростью. Смотрите предыдущий вопрос об обновлении данных графика здесь.

Просто обновите данные графика вместо добавления графиков. Это дает мне ускорение ~68% (12, 3 с до 4,0 с).

% ... your same setup
% Initialise plot data
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
plts = cell(4,3);
hh1 = cell(4,1);

% Loop over subplots and initialise plot lines
for p = 1:4
    hh1{p}=subplot(2,2,p);
    xlabel('$t$',options2{:});
    ylabel(ylabels{p},options2{:});
    title(state{p},options1{:})
    xlim([0 maxT])
    % Hold on to make 3 plots. Create initial points and set line styles.
    % Store the plots in a cell array for later reference.
    hold on
    plts{p,1} = plot(hh1{p},1:2,x(p,1:2),'b','linewidth',2);
    plts{p,2} = plot(hh1{p},1:2,z(p,1:2),'m');
    plts{p,3} = plot(hh1{p},1:2,x_est(p,1:2),':k','linewidth',2);
    hold off
end
% March through time. No replotting required, just update XData and YData
for k = 2:maxT
    for p = 1:4
        set(plts{p,1}, 'XData', 1:k, 'YData', x(p,1:k) );
        set(plts{p,2}, 'XData', 1:k, 'YData', z(p,1:k) );
        set(plts{p,3}, 'XData', 1:k, 'YData', x_est(p,1:k) );
    end
    drawnow;
end    

Теперь сюжет довольно оптимизирован. Если вы хотите, чтобы анимация была еще быстрее, просто строите каждый 2-й, 3-й,..., n-й временной шаг вместо каждого временного шага, используя for k = 2:n:maxT,

Другие вопросы по тегам