2013-09-02 20 views
13

jestem pomiaru jakiś kod w pętliMatlab tic toc dokładność

fps = zeros(1, 100); 
for i=1:100 

    t = tic 
    I = fetch_image_from_source(); % function to get image 
    fps(i) = 1./ toc(t); 

end 
plot(fps); 

I mam średnio 50 fps.

Następnie chciałbym dodać imshow() do mojego kodu. Rozumiem, że imshow jest bardzo powolna, ale nie będzie zawierała imshow wewnątrz tic-toc polecenia:

fps = zeros(1, 100); 
figure; 
for i=1:100 

    t = tic 
    I = fetch_image_from_source(); % function to get image 
    fps(i) = 1./ toc(t); 

    imshow(I); drawnow; 

end 
plot(fps); 

I dostać fps o 20% -30% wolniej. Dlaczego tak się dzieje? Ponieważ imshow() znajduje się poza tic-toc

+0

Jaka wersja MATLAB używasz? Czy te wyniki są spójne? Jeśli tak, spróbuj wyłączyć akcelerację JIT za pomocą funkcji "accel off" przed uruchomieniem tego i sprawdź, czy jest odtwarzalna. –

+0

Spróbuj także użyć FRAPS do pomiarów szybkości klatek. – Mikhail

Odpowiedz

4

Oto matlab's doc czas w ogóle, a jak upływający czas był i jest obecnie mierzone w Matlab. możemy przeczytać, że „tic i toc [oferty] najwyższa dokładność i najbardziej przewidywalne zachowanie”. Myślę, że to jest poprawne stwierdzenie.

Obserwowany spadek wydajności nie jest wynikiem złej miary upływu czasu i nie jest powiązany z funkcjami imshow lub drawnow. Będę argumentował, że jest on powiązany z systemem pamięci podręcznej.

Poniższy rysunek przedstawia wyniki czterech testów, z których każdy ma własną miarę bazową tic/toc (wykreśloną na niebiesko) dla 100 iteracji. Zielona linia pokazuje wyniki w różnych warunkach:

(1) for ii=1:100 
     t = tic;    %single tic/toc 
     fps(ii,2) = 1./toc(t); 
     rand(1000);    %extra function outside tic/toc 
     end 

Jak donosi w swoim pytaniu, możemy obserwować wolniejsze klatek na sekundę (fps; powiedziałbym 30%), mimo rand będącego zewnątrz tic bloku/toc . Dodatkowa funkcja może być dowolnego typu (plot, surf, imshow, sum), zawsze będziesz obserwować spadek wydajności.

(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 

W drugim podpólcie blok Tic/Toc powtarza się dwukrotnie. Pomiar fps jest zatem wykonywany dwa razy i zachowywany jest tylko drugi pomiar. Widzimy, że spadku wydajności już nie ma - tak jak pierwsze wezwanie Tic/Toc przygotowało drugie (rozgrzewka). Interpretuję to w kontekście pamięci podręcznej: instrukcje i/lub dane są wykonywane, a następnie przechowywane w pamięci niskiego poziomu - drugie połączenie jest szybsze.

(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 

Trzecie podplot wykorzystało 10.000 tic/toc jako dodatkową funkcję w scenariuszu pojedynczego połączenia. Możesz zobaczyć, że wydajność jest prawie identyczna.Cały zestaw danych/instrukcji w tym podpunkcie jest związany tylko z tic/toc - ponownie, z szybkim dostępem do pamięci podręcznej.

(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 

Wreszcie, czwarty wątek pokazuje dwa kolejne bloki połączeń tic/toc. Widzimy, że drugi działa lepiej niż pierwszy (efekt rozgrzewki).

Ogólny wzór pokazany tutaj nie jest związane z imshow, nie zależy od JIT z accel, ale zależy tylko od kolejnych połączeń do danej funkcji. Interpretuję to pod kątem pamięci podręcznej, ale brakuje mi formalnego dowodu.

Oto Działki

enter image description here

i kod

%% 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]); 
+0

+1: Interesujące. Zastanawiam się, czy na te testy ma wpływ funkcja "accel off". –

+0

@Eitan T - na te wzory nie ma wpływu funkcja (funkcja "accel", "wył."); "I" funkcja ("JIT", "wyłączone"); ". Ale może być inny powód spadku wydajności, ponieważ nie mam metody, aby powiedzieć "instrukcje/dane są przechowywane w pamięci podręcznej" - widzimy tylko produkty uboczne tutaj. – marsei

+0

Rozumiem to. Po prostu strzelaj w ciemność tutaj. Dostałeś jednak punkty za wysiłek. –

3

Może to być spowodowane możliwościami procesora wielowątkowego.

Liczba wątków obliczeniowych stosowanych przez MATLAB opiera się na wartości maxNumCompThreads. Jeśli ustawisz na 1, następnie oba przypadki powinny teoretycznie dają ten sam fps.

Można zrobić to osiągnąć jak:

LASTN = maxNumCompThreads(N); 

Tutaj N powinien być 1 i LASTN daje poprzednią maksymalną liczbę obliczeniowych wątków, które mogą być przydatne później w przypadku, gdy chcesz przywrócić preferencje .

+0

Dlaczego więc miałoby to wpłynąć na jedną sprawę, a nie na drugą? –

+0

@EitanT: Nie mam dostępu do MATLAB, aby potwierdzić teraz, ale domyślam się, że 'imshow' może być obsłużony przez dodatkowe wątki wchodzące w grę. –

+1

Nadal nie rozumiem, w jaki sposób uwzględniłoby to powodzenie_ spowodowane przez dodanie 'imshow' ... –