12

No tengo suficiente memoria para crear simplemente una matriz D-by-D diagonal, ya que D es grande. Sigo recibiendo un error de 'falta de memoria'.Multiplicación eficiente de matrices muy grandes en MATLAB

En lugar de realizar operaciones M x D x D en la primera multiplicación, hago operaciones M x D, pero aún así mi código tarda años en ejecutarse.

¿Alguien puede encontrar una manera más efectiva de realizar la multiplicación A'*B*A? Esto es lo que he intentado hasta ahora:

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

Estoy confundido. ¿Se supone que la matriz B es D-by-D o M-by-M? Tu imagen dice lo primero, pero tu código sugiere lo último. – gnovice

+0

bien descubierto, ahora corregido – matcheek

+0

Además, ¿está tratando de calcular A '* B * A, que le daría un resultado M-por-M? – gnovice

Respuesta

12

Una opción que debería resolver su problema es usar sparse matrices. Aquí está un ejemplo:

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 

Otra opción sería la de replicar los elementos D a lo largo de la diagonal principal de B para crear una matriz de M-por-D utilizando la función REPMAT, a continuación, utilizar element-wise multiplication con A.':

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

Y sin embargo, otra opción sería utilizar la función BSXFUN:

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

muchas gracias, me tomó horas llegar aquí – matcheek

+2

si la memoria es un problema, el 'bsxfun' es preferible a' repmat', porque no genera una matriz replicada. Sin embargo, 'bsxfun' no estuvo disponible hasta Matlab 2006 más o menos ... – shabbychef

+0

que explica mucho, aprendiendo todos los días – matcheek

3

Tal vez estoy teniendo un poco de un Brainfart aquí, pero no puedo dar vuelta a su matriz DxD en una matriz DxM (con M copias del vector que le dan) y luego. * las dos últimas matrices en lugar de multiplicarlas (y luego, por supuesto, normalmente multiplicar la primera con la cantidad de producto encontrado).

+0

No creo D x D debido a un "error de falta de memoria". Entonces sería fácil. Tu solución me da un error de 'falta de memoria' casi en el momento en que la mina tarda un poco más pero hace exactamente lo mismo. Ambos son correctos, pero las matrices son enormes. – matcheek

+0

Tanto mi solución como gnovice solo requieren almacenamiento O (DxM). No veo por qué mi solución es incorrecta mientras que la suya está bien. De hecho, su solución de repmat es mía exactamente (hasta el orden de multiplicación, que no importa). –

+0

gracias por su respuesta. Para que quede claro, intenté con su solución pero no pude superar el error de "falta de memoria". – matcheek

3
  1. Te estás "agotando la memoria" porque MATLAB no puede encontrar un trozo de memoria lo suficientemente grande como para acomodar toda la matriz. Existen diferentes técnicas para evitar este error descrito in MATLAB documentation.

  2. En MATLAB obviamente no necesita programar bucles explícitos en la mayoría de los casos porque puede usar el operador *. Existe una técnica para acelerar la multiplicación de matrices si se realiza con ciclos explícitos, aquí está an example in C#. Tiene una buena idea de cómo la matriz (potencialmente grande) se puede dividir en matrices más pequeñas. Para contener estas matrices más pequeñas en MATLAB, puede usar la matriz de celda. Es mucho más probable que el sistema encuentre suficiente RAM para acomodar dos submatrices más pequeñas luego la matriz grande resultante.

+1

Soy un gran ignorante y no he pensado por un momento en errores de caché, desenrollamiento de bucle o predicción de bifurcación , pero gracias por un recordatorio – matcheek

+0

@matcheek: la técnica de dividir una matriz grande en otras más pequeñas se puede aplicar a la RAM de la misma manera que se aplica a la memoria caché. Para usted caché no importa en absoluto, pero RAM lo hace. – Mikhail

Cuestiones relacionadas