How can i speed up this large matrix multiplications?

80 vues (au cours des 30 derniers jours)
Sinwoo Jeong
Sinwoo Jeong le 15 Oct 2018
Commenté : Sinwoo Jeong le 15 Oct 2018
Hello.
The purpose of my code is solving O.D.E. and in the function I need to do large matrix multiplication every single time step.
Therefore, almost all CPU time taken is consumed in this matrix multiplications.
I think mentioning every detail of my code is not necessary. So, only simplified code is uploaded as follows:
C = rand(10000, 5000);
B = rand(10000, 1000);
for i = 1:1000
A = rand(10000, 1);
D = (A.*B)'*C;
end
Here, B and C are constant matrix but A is changed in every single for loop. That's why I put A into a for loop. (I used function rand here just for a simple example) I've tried GPU, mex file, etc. But I have not been able to find the way which is faster than normal MATLAB .* or * operation. I think I can pre-calculate the value of the multiplication between B and C to avoid multiplying B to A and C to (A.*B) again. But I have no idea. Could you guys please help me?
(The matrix are defined as a sparse matrix in my actual code)

Réponse acceptée

Bruno Luong
Bruno Luong le 15 Oct 2018
Modifié(e) : Bruno Luong le 15 Oct 2018
There is also another way to precompute B*C as explained my answer on this similar question
It's actually very memory consuming for full matrix and noticeable slower due to inefficient memory access, even the FPU requirement is less.
However in some cases of SPARSE matrices, it can win, as showed in the test case bellow:
m = 5000;
n = 1000;
p = 10000;
C = sprand(p,m,1e-2);
B = sprand(p,n,1e-2);
A = rand(p,1);
tic
(A.*B).'*C;
toc % Elapsed time is 0.186504 seconds.
% Preparation step, must be carried out only once, since B and C are known
p = size(B,1);
[ib,jb,b] = find(B.');
[ic,jc,c] = find(C.');
commonj = intersect(jb,jc);
keepb=ismember(jb,commonj);
keepc=ismember(jc,commonj);
ib = ib(keepb);
jb = jb(keepb);
b = b(keepb);
ic = ic(keepc);
jc = jc(keepc);
c = c(keepc);
[~,locb]=ismember(jb,commonj);
[~,locc]=ismember(jc,commonj);
cb = accumarray(jb,ib,[p 1],@(x) {x});
cc = accumarray(jc,ic,[p 1],@(x) {x});
ifun = @(cb,cc) reshape(cb(:)+(cc(:).'-1)*size(B,2),[],1);
ibc = cellfun(ifun, cb, cc, 'unif', 0);
jfun = @(j) j+zeros(size(ibc{j}));
jbc = arrayfun(jfun, (1:p).', 'unif', 0);
b = accumarray(jb,b,[p 1],@(x) {x});
c = accumarray(jc,c,[p 1],@(x) {x});
vfun = @(b,c) reshape(b(:).*(c(:).'),[],1);
vbc = cellfun(vfun, b, c, 'unif', 0);
ibc = cat(1,ibc{:});
jbc = cat(1,jbc{:});
vbc = cat(1,vbc{:});
BC = sparse(ibc,jbc,vbc,size(B,2)*size(C,2),p);
%%this should be in the loop
tic
reshape(BC*A,size(B,2),[]);
toc % Elapsed time is 0.072390 seconds.
  3 commentaires
Sinwoo Jeong
Sinwoo Jeong le 15 Oct 2018
Modifié(e) : Sinwoo Jeong le 15 Oct 2018
OK. Thank you so much. I'm gonna look over it and tell you what I think. In my problem, matrix B and C are quite sparse. So, I think I will get a nice result thanks to your comment.
Sinwoo Jeong
Sinwoo Jeong le 15 Oct 2018
I think it works very well. You r a great genius.
Well, how did you come up with this brilliant idea?

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Sparse Matrices dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by