Ответ 1
Вот matlab doc о времени в целом и о том, как прошло время и в настоящее время измеряется в Matlab. Мы можем прочитать, что "tic и toc [предлагает] высочайшую точность и наиболее предсказуемое поведение". Я думаю, что это действительная инструкция.
Снижение производительности, наблюдаемое здесь, происходит не из-за плохой меры прошедшего времени, а также не связано с использованием функций imshow
или drawnow
. Я буду утверждать, что это связано с системой кэширования.
На приведенном ниже рисунке показаны результаты четырех тестов, каждый из которых имеет свою собственную базовую меру tic/toc
(нарисованную синим цветом) на 100 итераций. Зеленая линия показывает производительность в разных условиях:
(1) for ii=1:100
t = tic; %single tic/toc
fps(ii,2) = 1./toc(t);
rand(1000); %extra function outside tic/toc
end
Как сообщалось в вашем вопросе, мы можем наблюдать более медленный кадр в секунду (FPS, я бы сказал, 30%), несмотря на то, что rand
находится за пределами блока tic/toc. Дополнительная функция может быть любого типа (plot
, surf
, imshow
, sum
), вы всегда будете наблюдать за снижением производительности.
(2) for ii=1:100
t = tic; %first tic/toc
fps(ii,2) = 1./toc(t);
t = tic; %second tic/toc
fps(ii,2) = 1./toc(t);
rand(1000); %extra function outside tic/toc
end
Во втором подзаголовке блок tic/toc повторяется дважды. Поэтому измерение fps
выполняется два раза, и сохраняется только вторая мера. Мы видим, что падение производительности больше не существует - точно так же, как первый вызов tic/toc подготовил второй (разминка). Я интерпретирую это в терминах кеша: инструкции и/или данные выполняются, а затем хранятся в памяти низкого уровня - второй вызов выполняется быстрее.
(3) for ii=1:100
t = tic; %first tic/toc
fps(ii,2) = 1./toc(t);
for ij = 1:10000 %10,000 extra tic/toc
tic;
tmp = toc;
end
end
В третьем подзаголовке используется 10000 tic/toc в качестве дополнительной функции в сценарии с одним вызовом. Вы можете видеть, что производительность почти идентична. Весь набор данных/инструкций в этом подзаголовке связан только с tic/toc - опять же с быстрым доступом к кешу.
(4) for ii=1:100 %first tic/toc block
t = tic;
fps(ii,1) = 1./toc(t);
end
for ii=1:100 %second tic/toc block
t = tic;
fps(ii,2) = 1./toc(t);
end
Наконец, четвертый подзаголовок показывает два последовательных блока вызовов tic/toc. Мы видим, что второй работает лучше первого (эффект разогрева).
Общий шаблон, показанный здесь, не связан с imshow
, не зависит от JIT
от accel
, но зависит только от последовательных вызовов определенной функции. Я интерпретирую это с точки зрения кеша, но мне не хватает формальных доказательств.
Вот графики
и код
%% EXTRA FUNCTION (single call)
fps = zeros(2, 100);
% first case: 100 tic/toc
for ii=1:100
t = tic;
fps(ii,1) = 1./toc(t);
end
%second case: 100 tic/toc + additional function
for ii=1:100
t = tic;
fps(ii,2) = 1./toc(t);
% graph or scalar functions (uncomment to test)
%drawnow;
%plot(1:10)
rand(1000);
%ones(1000, 1000);
%sum(1:1000000);
%diff(1:1000000);
end
h = figure('Color','w','Position',[10 10 600 800]);
subplot(4,1,1);
plot(fps); legend({'tic/toc only','extra function'});
ylabel('FPS');
title('extra function, single call','FontSize',14);
set(gca,'FontSize',14, 'YLim', [0 3.5e5]);
%% EXTRA FUNCTION (double call)
fps = zeros(2, 100);
% first case: 100 tic/toc
for ii=1:100
t = tic;
fps(ii,1) = 1./toc(t);
end
%second case: 100 tic/toc + additional function (except tic/toc)
for ii=1:100
%first call
t = tic;
fps(ii,2) = 1./toc(t);
%second call (identical to first)
t = tic;
fps(ii,2) = 1./toc(t);
rand(1000);
end
subplot(4,1,2);
plot(fps); legend({'tic/toc only','extra function'});
ylabel('FPS');
title('extra function, double call','FontSize',14);
set(gca,'FontSize',14, 'YLim', [0 3.5e5]);
%% EXTRA FUNCTION (double call)
fps = zeros(2, 100);
% first case: 100 tic/toc
for ii=1:100
t = tic;
fps(ii,1) = 1./toc(t);
end
%second case: 100 tic/toc + 10000 tic/toc
for ii=1:100
t = tic;
fps(ii,2) = 1./toc(t);
for ij = 1:10000
tic;
tmp = toc;
end
end
subplot(4,1,3);
plot(fps); legend({'tic/toc','extra tic/toc'});
ylabel('FPS');
title('Identical function calls','FontSize',14);
set(gca,'FontSize',14, 'YLim', [0 3.5e5]);
%% TIC/TOC call twice
fps = zeros(2, 100);
% first case: 100 tic/toc
for ii=1:100
t = tic;
fps(ii,1) = 1./toc(t);
end
for ii=1:100
t = tic;
fps(ii,2) = 1./toc(t);
end
subplot(4,1,4);
plot(fps); legend({'tic/toc (1)','tic/toc (2)'});
ylabel('FPS');
title('tic/toc twice','FontSize',14);
set(gca,'FontSize',14, 'YLim', [0 3.5e5]);