Most efficient way to add multiple sparse matrices in a loop in MATLAB
20 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Kobye
el 15 de Abr. de 2015
Comentada: Zoltán Csáti
el 4 de Nov. de 2017
I have a code that repeatedly calculates a sparse matrix in a loop (it performs this calculation 13472 times to be precise). Each of these sparse matrices is unique.
After each execution, it adds the newly calculated sparse matrix to what was originally a sparse zero matrix.
When all 13742 matrices have been added, the code exits the loop and the program terminates.
The code bottleneck occurs in adding the sparse matrices. I have made a dummy version of the code that exhibits the same behavior as my real code. It consists of a MATLAB function and a script given below.
(1) Function that generates the sparse matrix:
function out = test_evaluate_stiffness(n)
ind = randi([1 n*n],300,1);
val = rand(300,1);
[I,J] = ind2sub([n,n],ind);
out = sparse(I,J,val,n,n);
end
(2) Main script (program)
% Calculate the stiffness matrix
n=1000;
K=sparse([],[],[],n,n,n^2);
tic
for i=1:13472
temp=rand(1)*test_evaluate_stiffness(n);
K=K+temp;
end
fprintf('Stiffness Calculation Complete\nTime taken = %f s\n',toc)
I'm not very familiar with sparse matrix operations so I may be missing a critical point here that may allow my code to be sped up considerably.
Am I handling the updating of my stiffness matrix in a reasonable way in my code? Is there another way that I should be using sparse that will result in a faster assembly?
Note that I have coupling in my system so the the values by which I augment my global stiffness matrix in each loop execution aren't necessarily on the diagonal.
A profiler report is also provided below:
%
0 comentarios
Respuesta aceptada
John D'Errico
el 15 de Abr. de 2015
Editada: John D'Errico
el 15 de Abr. de 2015
The problems is? You are doing it wrong. Flat out, wrong.
NEVER build a sparse matrix up like this. NEVER. NEVER. If I say it 3 times, it must be true.
The problem is that every time you add new entries to the matrix, it must move those elements around in memory. EVERY time. Plus, there are more elements that are non-zero in the final matrix for every iteration, so it gets a little larger every time. So more memory must be allocated. This is the classic problem of dynamic allocation.
The answer? Do it the right way! There is a far better way to solve this problem.
Don't create a sparse matrix on every iteration. Instead, just store the non-zero elements. I would suggest storing them in a simple flat array, with 3 columns for each iteration. Since you know there will be 13472 sub-arrays, save them as cells of a cell array.
C = cell(13472,1);
Now, on each iteration, stuff one cell with the information needed to create the sub-array, thus
for i = 1:13472
.... stuff ...
C{i} = [I,J,Val];
end
Now, AFTER the loop is done, concatenate all of those cells into ONE array.
IJV = cell2mat( C );
Finally, ONLY now do you want to call sparse. CALL IT ONE TIME. I'll assume the final size of the array is known to be n by m.
A = sparse(IJV(:,1),IJV(:,2),IJV(:,3),n,m);
In the event that you do not know how many sub-arrays you wish to sum, there are still good ways to solve the problem, accumulating the information in cell array elements. You can find tools to do this on the file exchange, in the form of my growdata tools.
Learn to build sparse matrices efficiently. There are god ways, and there are obscenely bad ways to do almost anything.
5 comentarios
Stephen23
el 5 de Abr. de 2017
@John D'Errico: how does this add the values if two cells address the same location in the sparse array?
Zoltán Csáti
el 4 de Nov. de 2017
@Stephen Cobeldick: the sparse command has this assumption. See: https://nl.mathworks.com/help/matlab/ref/sparse.html#bul62_1
Más respuestas (1)
James Tursa
el 15 de Abr. de 2015
Editada: James Tursa
el 15 de Abr. de 2015
Unless you know in advance the pattern of the non-zero spots and can exploit that, then I think you are stuck. At every iteration of K = K + temp, the entire data area of K in general will need to be copied to a new memory location and the temp data will need to be added/merged in as well.
If you do know the pattern in advance, then possibly something could be done to minimize the data copying.
How big is n in your real problem? Can you do some calculations in full and then convert to sparse later for your downstream needs?
4 comentarios
John D'Errico
el 15 de Abr. de 2015
See my answer. There are good ways to do this without resorting to mex.
Ver también
Categorías
Más información sobre Logical en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!