Как ускорить очень медленный анимационный сюжет в 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
,