12

Tôi không có đủ bộ nhớ để tạo một ma trận D-by-D chéo, vì D lớn. Tôi tiếp tục bị lỗi 'hết bộ nhớ'.Hiệu quả nhân các ma trận rất lớn trong MATLAB

Thay vì thực hiện các thao tác M x D x D trong phép nhân thứ nhất, tôi thực hiện các thao tác M x D, nhưng mã của tôi vẫn mất nhiều thời gian để chạy.

Ai có thể tìm cách hiệu quả hơn để thực hiện phép nhân A'*B*A? Dưới đây là những gì tôi đã cố gắng cho đến nay:

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

Tôi đang bối rối. Ma trận B có phải là D-by-D hay M-by-M không? Hình ảnh của bạn nói rằng trước đây nhưng mã của bạn cho thấy sau này. – gnovice

+0

cũng được phát hiện, hiện đã sửa đổi – matcheek

+0

Ngoài ra, bạn đang cố tính A * B * A, điều này sẽ cho bạn kết quả M-by-M? – gnovice

Trả lời

12

Một tùy chọn cần giải quyết vấn đề của bạn là sử dụng sparse matrices. Dưới đây là một ví dụ:

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 

Một lựa chọn khác sẽ được tái tạo các yếu tố D dọc theo đường chéo chính của B để tạo ra một ma trận M-by-D sử dụng chức năng REPMAT, sau đó sử dụng element-wise multiplication với A.':

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

Tuy nhiên tùy chọn khác sẽ được sử dụng chức năng BSXFUN:

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

cảm ơn rất nhiều, tôi đã cho tôi giờ để có được ở đây – matcheek

+2

nếu bộ nhớ là một vấn đề, 'bsxfun' được ưa thích để' repmat', bởi vì nó không sinh ra một ma trận nhân rộng. Tuy nhiên, 'bsxfun' không có sẵn cho đến khi Matlab 2006 hay như vậy ... – shabbychef

+0

hơn là giải thích rất nhiều, học tập hàng ngày – matcheek

3

Có lẽ tôi đang gặp một chút của một brainfart ở đây, nhưng bạn không thể tắt ma trận DxD của bạn vào một ma trận DXM (với M bản của vectơ bạn đã cho) và sau đó * hai ma trận cuối thay vì nhân chúng (và sau đó, tất nhiên, thường nhân với số đầu tiên với số lượng sản phẩm tìm thấy)?

+0

Tôi không tạo D x D vì 'hết lỗi bộ nhớ' nó sẽ dễ dàng sau đó. Giải pháp của bạn mang lại cho tôi một lỗi 'hết bộ nhớ' gần như tại chỗ tôi mất nhiều thời gian hơn nhưng thực hiện chính xác như vậy. Cả hai đều đúng, nhưng ma trận rất lớn. – matcheek

+0

Cả giải pháp và gnovice của tôi chỉ yêu cầu lưu trữ O (DxM). Tôi không hiểu tại sao giải pháp của tôi không chính xác trong khi anh ấy ổn. Trong thực tế, giải pháp repmat của ông là của tôi chính xác (lên đến thứ tự của phép nhân, mà không quan trọng). –

+0

cảm ơn bạn đã trả lời. Để làm rõ, tôi đã thử giải pháp của bạn nhưng không thể khắc phục lỗi 'hết bộ nhớ'. – matcheek

3
  1. Bạn đang nhận được "hết bộ nhớ" vì MATLAB không thể tìm thấy một đoạn bộ nhớ đủ lớn để chứa toàn bộ ma trận. Có các kỹ thuật khác nhau để tránh lỗi này được mô tả in MATLAB documentation.

  2. Trong MATLAB, bạn rõ ràng không cần lập trình vòng lặp rõ ràng trong hầu hết các trường hợp vì bạn có thể sử dụng toán tử *. Có tồn tại một kỹ thuật làm thế nào để tăng tốc độ nhân ma trận nếu nó được thực hiện với vòng lặp rõ ràng, đây là an example in C#. Nó có một ý tưởng tốt như thế nào (có tiềm năng lớn) ma trận có thể được chia thành các ma trận nhỏ hơn. Để chứa các ma trận nhỏ hơn này trong MATLAB, bạn có thể sử dụng ma trận ô. Nó có thể là nhiều hơn nữa mà hệ thống tìm đủ RAM để chứa hai ma trận nhỏ hơn sau đó kết quả là ma trận lớn.

+1

Tôi là một người dốt nát lớn và không có sự kiện suy nghĩ trong giây lát về nhớ cache, bỏ vòng lặp hoặc dự đoán nhánh , nhưng nhờ một lời nhắc nhở – matcheek

+0

@matcheek: kỹ thuật tách một ma trận lớn thành các ma trận nhỏ hơn có thể được áp dụng cho RAM giống như cách nó được áp dụng cho bộ nhớ cache. Đối với bạn bộ nhớ cache không quan trọng ở tất cả, nhưng RAM nào. – Mikhail

Các vấn đề liên quan