Подтвердить что ты не робот

Эффективное умножение очень больших матриц в MATLAB

У меня недостаточно памяти, чтобы просто создать диагональную матрицу D-by-D, так как D велико. Я продолжаю получать ошибку "из памяти".

Вместо выполнения операций M x D x D в первом умножении, я выполняю операции M x D, но мой код занимает много времени.

Может ли кто-нибудь найти более эффективный способ выполнения умножения A'*B*A? Вот что я сделал до сих пор:

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

4b9b3361

Ответ 1

Один из вариантов, который должен решить вашу проблему, - это разреженные матрицы. Вот пример:

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

Другим вариантом будет репликация элементов D по главной диагонали B для создания матрицы M-by-D с использованием функции REPMAT, затем используйте умножение по элементам с помощью A.':

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

И еще одним вариантом было бы использовать функцию BSXFUN:

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

Ответ 2

Может быть, у меня здесь немного мозгового мозга, но вы не можете превратить свою матрицу DxD в матрицу DxM (с M копиями вектора, который вы указали), а затем. * последние две матрицы, а не умножьте их (а затем, конечно, обычно умножайте первую на найденную величину продукта)?

Ответ 3

  • Вы получаете "вне памяти", потому что MATLAB не может найти кусок памяти, достаточно большой для размещения всей матрицы. Существуют различные способы избежать этой ошибки, описанной в документации MATLAB.

  • В MATLAB вам явно не нужно программировать явные петли в большинстве случаев, потому что вы можете использовать оператор *. Существует метод ускорения матричного умножения, если это делается с явными циклами, здесь пример в С#. У него есть хорошая идея, как (потенциально большая) матрица может быть разбита на более мелкие матрицы. Чтобы содержать эти меньшие матрицы в MATLAB, вы можете использовать клеточную матрицу. Гораздо более вероятно, что система найдет достаточное количество ОЗУ для размещения двух меньших субматриц, а затем получившейся большой матрицы.