2013-04-17 16 views
11

Byłem zaskoczony, aby znaleźć następujące koszty różnicy między systemem MATLAB dla pętli:Najlepsze praktyki dla MATLAB dla indeksu pętli

ksize = 100; 
klist = 1:ksize; 

tic 
for m = 1:100000   
    for k = 1:ksize 

    end   
end 
toc 

tic 
for m = 1:100000   
    for k = klist 

    end   
end 
toc 

Jedyną różnicą jest sposób lista indeks jest tworzony. Podejrzewałbym, że druga wersja będzie szybsza, ale lo!

Elapsed time is 0.055400 seconds. 
Elapsed time is 1.695904 seconds. 

Moje pytanie jest dwojaki: czym jest odpowiedzialny za rezultat powyżej, a gdzie indziej jest to niuans (lub podobnej nich) występują w programowaniu MATLAB? Mam nadzieję, że będę w stanie lepiej wykryć te nieefektywności w przyszłości. Dziękuje wszystkim.

+3

Jest to prawdopodobnie spowodowane akceleracją JIT, ponieważ jeśli wyłączysz ją za pomocą funkcji "accel off", otrzymasz podobne wyniki dla obu serii. –

Odpowiedz

4

Dokumentacja w for() stanów:

for index = values 
    ... 
end 

gdzie values ma jedną z następujących form:

  • ...

  • valArray: tworzy indeks kolumny wektor z kolejnych kolumn tablicy valArray na każdym iteracja. Na przykład w pierwszej iteracji: index = valArray(:,1). Pętla jest wykonywana maksymalnie przez n razy, gdzie n jest liczbą kolumn valArray, podaną przez numel(valArray, 1, :). Dane wejściowe valArray mogą być dowolnego typu danych MATLAB, w tym ciągu, komórki lub struktury.

Dlatego zakładam istnieje znacząca napowietrznych i kompilator nie sprawdza, czy 1:ksize == klist wykorzystać szybszą realizację. Innymi słowy, zgodnie z komentarzem Eitana, JIT odnosi się do dwóch pierwszych typów akceptowanych wartości :.

Cały problem jest związany z poniższego zadania indeksowania (kolumna vs elementu):

tic 
for m = 1:100000   
    for k = 1:ksize 
     klist(:,k); 
    end   
end 
toc 

tic 
for m = 1:100000   
    for k = 1:ksize 
     klist(k); 
    end   
end 
toc 

Index column: ~2.9 sec 
Index element: ~0.28 sec 

Można zobaczyć, jak klist(:,k) skutecznie spowalnia szybszej pętli wskazujący, że problem w for k = klist jest związane z indeksowaniem kolumnowej użyte w tym przypadku.

Aby uzyskać dodatkowe informacje, patrz: lengthy discussion on (inefficient) indexing.

2

Moja odpowiedź to spekulacja (ponieważ tylko faceci z Mathworks znają implementację swojego produktu), ale myślę, że pierwsza pętla k jest zoptymalizowana, aby nie tworzyć rzeczywistej tablicy indeksów, ale po prostu skanować je jeden po drugim, ponieważ wyraźnie pokazuje, w jaki sposób wartości są "budowane". Druga pętla k nie może być zoptymalizowana, ponieważ interpreter nie wie z góry, czy zawartość tablicy indeksowej będzie rosła równomiernie. Tak więc, za każdym razem, gdy pętla się rozpocznie, uzyska dostęp do oryginalnej wersji, dzięki czemu uzyskasz obniżenie wydajności.

Później edytuj „on the fly” Kolejna kara wydajność może wynosić od indeksowanego dostępu int tablicy klist, w porównaniu do tworzenia wartości indeksu

+0

Zastanawiam się, czy mógłbyś to przetestować, tworząc klasę wywodzącą się z 'double' i przesłonięcie' copy' ... – wakjah

+0

@wakjah Checked, i nie chodzi o kopiowanie (nie ma żadnego kopiowania w rzeczywistości - myślę, że kopiowanie -write nadal działa). Chodzi o indeks odniesienia w "klist". Poprawiłem mt post. Dzięki za pomysł. –

+0

@wakjah Z drugiej strony, 'copy' działa na podklasach uchwytów i nie można dziedziczyć wartości * i * obsługi klas w tym samym czasie (nie słysząc w R2010a, że ​​mam). Zastanawiam się, czy faktycznie przesłoniłem cokolwiek ...: D –