Как ускорить очень медленный анимационный сюжет в MATLAB - PullRequest
0 голосов
/ 30 апреля 2018

Я пытаюсь создать анимированный сюжет, но мой код очень медленный, возможно, метод, который я использую, слишком наивен. В приведенном ниже примере у меня есть 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 Ответ

0 голосов
/ 30 апреля 2018

Поскольку вам нужна анимация, нет альтернативы использованию 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...