12

Nie mam wystarczającej ilości pamięci, aby utworzyć macierz diagonalną D-by-D, ponieważ D jest duże. Wciąż pojawia się błąd "braku pamięci".Efektywne mnożenie bardzo dużych macierzy w MATLAB

Zamiast wykonywać operacje M x D x D w pierwszym mno eniu, wykonuję operacje M x D, ale mój kod trwa do wieków.

Czy ktokolwiek może znaleźć skuteczniejszy sposób przeprowadzenia mnożenia A'*B*A? Oto co mam próbowano do tej pory:

D=20000 
M=25 

A = floor(rand(D,M)*10); 
B = floor(rand(1,D)*10); 

for i=1:D 
    for j=1:M 
     result(i,j) = A(i,j) * B(1,j); 
    end 
end  

manual = result * A'; 
auto = A*diag(B)*A'; 
isequal(manual,auto) 

alt text

+0

Jestem zdezorientowany. Czy macierz B ma być D-przez-D czy M-by-M? Twój obraz mówi o tym pierwszym, ale twój kod sugeruje to drugie. – gnovice

+0

dobrze zauważony, teraz poprawiony – matcheek

+0

Ponadto, czy próbujesz obliczyć A '* B * A, który dałby ci wynik M-by-M? – gnovice

Odpowiedz

12

Jedną z opcji, która powinna rozwiązać problem, jest użycie sparse matrices. Oto przykład:

D = 20000; 
M = 25; 
A = floor(rand(D,M).*10); %# A D-by-M matrix 
diagB = rand(1,D).*10;  %# Main diagonal of B 
B = sparse(1:D,1:D,diagB); %# A sparse D-by-D diagonal matrix 
result = (A.'*B)*A;   %'# An M-by-M result 

Innym rozwiązaniem byłoby replikacji elementy D wzdłuż głównej przekątnej B utworzyć macierz M-by-D przy użyciu funkcji REPMAT, a następnie użyć element-wise multiplication z A.':

B = repmat(diagB,M,1); %# Replicate diagB to create an M-by-D matrix 
result = (A.'.*B)*A; %'# An M-by-M result 

a jeszcze inna opcja byłoby użyć funkcji BSXFUN:

result = bsxfun(@times,A.',diagB)*A; %'# An M-by-M result 
+0

wielkie dzięki, zajęło mi godziny, aby uzyskać tutaj – matcheek

+2

jeśli pamięć jest problemem, 'bsxfun' jest preferowany do' repmat', ponieważ nie odradza się replikowanej macierzy. Jednak "bsxfun" nie stał się dostępny do czasu Matlab 2006 lub tak ... – shabbychef

+0

niż wiele wyjaśnia, ucząc się codziennie – matcheek

3

Może mam trochę brainfart tutaj, ale nie można włączyć matrycę dxd do matrycy DXM (z M egzemplarzy podanego wektora), a następnie. * dwie ostatnie macierze zamiast ich mnożyć (a następnie, oczywiście, normalnie pomnożyć pierwszą z ilością znalezionych produktów)?

+0

Nie tworzę DX D z powodu "błędu braku pamięci", to byłoby wtedy łatwe. Twoje rozwiązanie daje mi błąd "z pamięci" prawie na miejscu kopalnia trwa nieco dłużej, ale robi dokładnie to samo. Oba są poprawne, ale macierze są ogromne. – matcheek

+0

Zarówno moje rozwiązanie, jak i gnovice wymagają tylko pamięci O (DxM). Nie rozumiem, dlaczego moje rozwiązanie jest nieprawidłowe, podczas gdy jego jest w porządku. Rzeczywiście, jego rozwiązanie repmatyczne jest dokładnie moje (do porządku mnożenia, co nie ma znaczenia). –

+0

dziękuję za odpowiedź. Aby było jasne, próbowałem Twojego rozwiązania, ale nie mogłem przezwyciężyć błędu "braku pamięci". – matcheek

3
  1. Dostajesz "brak pamięci", ponieważ MATLAB nie może znaleźć fragmentu pamięci wystarczająco dużego, aby pomieścić całą macierz. Istnieją różne techniki, aby uniknąć tego błędu opisanego jako in MATLAB documentation.

  2. W MATLAB w większości przypadków nie potrzebujesz programowania jawnych pętli, ponieważ możesz użyć operatora *. Istnieje technika, jak przyspieszyć mnożenie macierzy, jeśli odbywa się z jawnymi pętlami, tutaj jest an example in C#. Dobrze wie, jak (potencjalnie dużą) matrycę można podzielić na mniejsze macierze. Aby pomieścić te mniejsze macierze w MATLAB można użyć macierzy komórek. O wiele bardziej prawdopodobne jest, że system znajdzie wystarczającą ilość pamięci RAM, aby pomieścić dwie mniejsze pod-macierze, a następnie powstałą dużą matrycę.

+1

Jestem wielkim ignorantem i nie myślę przez chwilę o chybionych pamięciach podręcznych, rozwijaniu pętli lub prognozowaniu gałęzi , ale dzięki za przypomnienie – matcheek

+0

@ matcheek: technika podziału dużej matrycy na mniejsze może być zastosowana do pamięci RAM w ten sam sposób, w jaki jest stosowana do pamięci podręcznej. Dla ciebie pamięć podręczna nie ma znaczenia, ale RAM ma. – Mikhail