2013-08-28 14 views
5

Ta obserwacja nie jest ważna, ponieważ czas stracony na instrukcjach pętli będzie prawdopodobnie znacznie wyższy niż sama pętla. Ale tak czy inaczej podzielę się tym, odkąd przeszukałem i nie mogłem znaleźć tematu na ten temat. Zawsze miałem wrażenie, że wstępna alokacja tablicy, którą chciałbym zapętlić, a następnie ją zapętlić, byłaby lepsza niż zapętlenie bezpośrednio na niej i postanowiłam ją sprawdzić. Kod byłoby porównanie wydajności między tych dwóch Fors:Wykonanie instrukcji pętli i wstępne przydzielenie samej instrukcji pętli

disp('Pure for with column on statement:') 
tic 
for k=1:N 
end 
toc 

disp('Pure for with column declared before statement:') 
tic 
m=1:N; 
for k=m 
end 
toc 

ale wyniki I got to:

Pure for with column on statement: 
Elapsed time is 0.003309 seconds. 
Pure for with column declared before statement: 
Elapsed time is 0.208744 seconds. 

Dlaczego, do cholery, jest? Czy wstępne przydzielanie nie powinno być szybsze?

W rzeczywistości, Matlab help for mówi:

długie pętle są bardziej efektywne, gdy pamięć wyrażenie grubego pojawia w sprawozdaniu za ponieważ wektor wskaźnik nie jest tworzony.

więc sprzeczne moje oczekiwania wyrażenie kolumny w instrukcji for jest lepsza, ponieważ nie przeznaczyć wektor a, z powodu, że jest szybszy.

zrobiłem następujący skrypt do testowania innych okazjach, że ja też pomyśli, że będzie szybciej:

% For comparison: 
N=1000000; 

disp('Pure for loop on cell declared on statement:') 
tic 
for k=repmat({1},1,N) 
end 
toc 

disp('Pure for loop on cell declared before statement:') 
tic 
mcell=repmat({1},1,N); 
for k=mcell 
end 
toc 

disp('Pure for loop calculating length on statement:') 
tic 
for k=1:length(mcell) 
end 
toc 

disp('Pure for loop calculating length before statement:') 
tic 
lMcell = length(mcell); 
for k=1:lMcell 
end 
toc 

disp('Pure while loop using le:') 
% While comparison: 
tic 
k=1; 
while (k<=N) 
    k=k+1; 
end 
toc 

disp('Pure while loop using lt+1:') 
% While comparison: 
tic 
k=1; 
while (k<N+1) 
    k=k+1; 
end 
toc 


disp('Pure while loop using lt+1 pre allocated:') 
tic 
k=1; 
myComp = N+1; 
while (k<myComp) 
    k=k+1; 
end 
toc 

A czasy są:

Pure for loop on cell declared on statement: 
Elapsed time is 0.259250 seconds. 
Pure for loop on cell declared before statement: 
Elapsed time is 0.260368 seconds. 
Pure for loop calculating length on statement: 
Elapsed time is 0.012132 seconds. 
Pure for loop calculating length before statement: 
Elapsed time is 0.003027 seconds. 
Pure while loop using le: 
Elapsed time is 0.005679 seconds. 
Pure while loop using lt+1: 
Elapsed time is 0.006433 seconds. 
Pure while loop using lt+1 pre allocated: 
Elapsed time is 0.005664 seconds. 

Wnioski:

  • Możesz uzyskać trochę wydajności po pętli na przecinkach, ale to może być pomijalne w porównaniu do czasu spędzonego na e for-loop.
  • Dla komórek różnica wydaje się być nieistotna.
  • Lepiej jest wstępnie przydzielić długość przed wykonaniem pętli.
  • Chwila ma taką samą wydajność jak dla bez bez wstępnego przydzielenia wektora, co ma sens, jak podano wcześniej:
  • Lepiej obliczyć wyrażenia stałe przed instrukcją while.

Ale pytanie, na które nie mogę odpowiedzieć, to co z komórką, dlaczego nie ma różnicy czasu? Koszt może być znacznie niższy niż obserwowany? Lub musi przydzielić komórki, ponieważ nie jest typem podstawowym jako podwójnym?

Jeśli znasz inne sztuczki dotyczące tego tematu, wypełnij i dodaj.


Wystarczy dodanie czasy, aby pokazać wyniki obracając feature('accel','off') jak powiedział @ odpowiedź Magla użytkownika.

Pure for with column on statement: 
Elapsed time is 0.181592 seconds. 
Pure for with column declared before statement: 
Elapsed time is 0.180011 seconds. 
Pure for loop on cell declared on statement: 
Elapsed time is 0.242995 seconds. 
Pure for loop on cell declared before statement: 
Elapsed time is 0.228705 seconds. 
Pure for loop calculating length on statement: 
Elapsed time is 0.178931 seconds. 
Pure for loop calculating length before statement: 
Elapsed time is 0.178486 seconds. 
Pure while loop using le: 
Elapsed time is 1.138081 seconds. 
Pure while loop using lt+1: 
Elapsed time is 1.241420 seconds. 
Pure while loop using lt+1 pre allocated: 
Elapsed time is 1.162546 seconds. 

Wyniki teraz miejsca zgodnie z oczekiwaniami ...

Odpowiedz

3

To stwierdzenie nie ma nic wspólnego z preallocating czy nie: zajmuje się włączyć lub Matlab jest nie do obliczenia rzeczy z kilku rdzeni. Po wstawieniu operatora dwukropka w instrukcji for, mówi matlab, aby używał kilku rdzeni (tj. Wielowątkowość).

Jeśli ustawisz matlab na jednym rdzeniu tylko z feature('accel','off'), obserwowana różnica z doubles zniknie. W odniesieniu do cells, matlab nie używa wielowątkowości - dlatego nie można zaobserwować żadnej różnicy (niezależnie od statusu accel).

Pętla for jest wielowątkowa, gdy używany jest dwukropek i tylko w przypadku dwukropka. Następujące wektory podobnej długości, nie łączy się kilka rdzeni:

  • for k = randperm(N)
  • for k = linspace(1,N,N)

ale for k = 1:0.9999:N jest wielowątkowe.

Jedno wytłumaczenie można znaleźć na tej stronie matlab's support page. Stwierdza, że ​​przetwarzanie wielordzeniowe może być wykonane, gdy "Operacje w algorytmie przeprowadzanym przez funkcję są łatwo podzielone na sekcje, które mogą być wykonywane równocześnie.". Z operatorem dwukropka, Matlab wie, że for może być podzielony na partycje.

+0

Teraz ma sens ... dziękuję! – Werner

+3

W jaki sposób Matlab może z góry wiedzieć, że wielowątkowe pętle 'for' są bezpieczne? Rozumiem, że Matlab będzie natywnie wielowątkowe funkcje, takie jak 'fft',' eig', 'svd' i' sort', ale uzyskanie wielowątkowości w pętli wymaga zestawu narzędzi do przetwarzania równoległego i konstrukcji 'parfor' ... Czy istnieje oficjalna dokumentacja omawiająca tę funkcję? –

+0

@Colin T Bowers - zobacz edycję. Do mojego zrozumienia; funkcja 'parfor' jest używana do wielowątkowej zawartości bloku' for'. Tutaj jest to tylko powtarzalne wywołanie funkcji, które jest oceniane. – marsei

Powiązane problemy