2015-02-25 9 views
21

Próbuję znaleźć najszybszy sposób standaryzacji macierzy w Matlab (średnia zero, kolumny wariancji jednostek). Wszystko sprowadza się do tego, który jest najszybszym sposobem zastosowania tej samej operacji do wszystkich wierszy w macierzy. Każdy post, który przeczytałem, doszedł do tego samego wniosku: użyj bsxfun zamiast repmat. Ten artykuł, napisany przez Mathworks, jest przykładem: http://blogs.mathworks.com/loren/2008/08/04/comparing-repmat-and-bsxfun-performance/Matlab - bsxfun nie jest już szybszy od repmat?

Jednak przy próbie tego na moim komputerze repmat jest zawsze szybszy. Oto moje wyniki przy wykorzystaniu tego samego kodu, jak w artykule:

m = 1e5; 
n = 100; 
A = rand(m,n); 

frepmat = @() A - repmat(mean(A),size(A,1),1); 
timeit(frepmat) 

fbsxfun = @() bsxfun(@minus,A,mean(A)); 
timeit(fbsxfun) 

Wyniki:

ans = 

    0.0349 


ans = 

    0.0391 

W rzeczywistości, nigdy nie mogę dostać bsxfun wykonać lepiej niż repmat w tej sytuacji nie ma znaczenia, jak małe lub duża jest matryca wejściowa.

Czy ktoś może to wyjaśnić?

+1

Dla mnie podejście bsxfun jest zawsze szybsze, także dla większych tablic. (Matlab 2014a) – thewaywewalk

+0

Dla mnie (R2014b) wygrywa bsxfun. Jakiej wersji Matlab używasz? –

+0

Próbowałem go zarówno w 2014a i 2014b. Czy system operacyjny może coś zmienić? Jestem na OSX. – user1337

Odpowiedz

11

Większość porad, które czytasz, w tym wpis na blogu od Loren, prawdopodobnie odnosi się do starych wersji MATLAB, dla których bsxfun był nieco szybszy niż repmat. W wersji R2013b (patrz sekcja "Wydajność" w łączu), repmat zostało ponownie zaimplementowane, aby zapewnić dużą poprawę wydajności w przypadku zastosowania do argumentów liczbowych, char i logicznych. W najnowszych wersjach może mieć mniej więcej taką samą prędkość, co bsxfun.

Na co warto, na moim komputerze z R2014a uzyskać

m = 1e5; 
n = 100; 
A = rand(m,n); 

frepmat = @() A - repmat(mean(A),size(A,1),1); 
timeit(frepmat) 

fbsxfun = @() bsxfun(@minus,A,mean(A)); 
timeit(fbsxfun) 

ans = 
     0.03756 
ans = 
    0.034831 

tak wygląda bsxfun jest jeszcze odrobinę szybciej, ale nie za dużo - i na komputerze wydaje się odwrotna jest przypadek . Oczywiście wyniki te mogą się różnić, jeśli zmienisz rozmiar A lub operacji, którą aplikujesz.

Możliwe, że istnieją jeszcze inne powody, by preferować jedno rozwiązanie nad drugim, takie jak elegancja (wolę bsxfun, jeśli to możliwe).


Edit: komentujących prosić o konkretnego powodu wolą bsxfun, co oznacza, że ​​może on użyć mniej pamięci niż repmat unikając tymczasową kopię że repmat nie.

Nie sądzę, że tak jest w rzeczywistości. Na przykład, otwarty Menedżer zadań (lub równowartość w systemie Linux/Mac), oglądać poziomy pamięci i wpisz:

>> m = 1e5; n = 8e3; A = rand(m,n); 
>> B = A - repmat(mean(A),size(A,1),1); 
>> clear B 
>> C = bsxfun(@minus,A,mean(A)); 
>> clear C 

(Dostosuj m i n aż skoki są widoczne na wykresie, ale nie tak duże cię zabrakło pamięci).

widzę dokładnie takie samo zachowanie z obu repmat i bsxfun, który jest, że pamięć wzrasta płynnie do nowego poziomu (w zasadzie podwojenie rozmiaru A) bez dodatkowego tymczasowego szczytu.

Jest tak również w przypadku, gdy operacja jest wykonywana w miejscu.Znowu oglądać pamięci i jej rodzaju:

>> m = 1e5; n = 8e3; A = rand(m,n); 
>> A = A - repmat(mean(A),size(A,1),1); 
>> clear all 
>> m = 1e5; n = 8e3; A = rand(m,n); 
>> A = bsxfun(@minus,A,mean(A)); 

znowu widzę dokładnie takie samo zachowanie z obu repmat i bsxfun, który jest, że pamięć wznosi się na szczyt (w zasadzie podwojenie rozmiaru A), a następnie wraca do poprzedniego poziomu.

Obawiam się, że nie widzę dużej różnicy technicznej pod względem prędkości ani pamięci między repmat i bsxfun. Moja preferencja dla bsxfun jest naprawdę tylko osobistą preferencją, ponieważ wydaje się nieco bardziej elegancka.

+1

'bsxfun' nadal ma tę zaletę, że zużywa mniej pamięci, ponieważ wewnętrznie unika powtarzania danych, czy mam rację? Mam na myśli podać uzasadnienie preferencji dla 'bsxfun'! :-) –

+0

@LuisMendo jest możliwe, że ponowne wprowadzenie 'repmat' unika wyraźnej kopii pamięci? Czy możliwe jest zaimplementowanie "leniwej" kopii? Nie mam dostępu do najnowszych wersji Matlab ... – Shai

+0

@Shai Tak, właśnie o to mi chodziło z moim pytaniem. Możliwe, że 'repmat' wewnętrznie dokonuje jakiejś optymalizacji. Nie wiem Ale nadal wolę 'bsxfun'! –

Powiązane problemy