在MATLAB中在循环中添加多个稀疏矩阵的最快方法

时间:2015-04-15 19:21:19

标签: matlab sparse-matrix

我有一个重复计算循环中稀疏矩阵的代码(它精确地执行13472次计算)。这些稀疏矩阵中的每一个都是唯一的。

每次执行后,它会将新计算的稀疏矩阵添加到最初的稀疏零矩阵中。

当添加了所有13742个矩阵后,代码退出循环并且程序终止。

添加稀疏矩阵时会出现代码瓶颈。我制作了一个虚拟版本的代码,它表现出与我的真实代码相同的行为。它由MATLAB函数和下面给出的脚本组成。

(1)生成稀疏矩阵的函数:

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)主要脚本(程序)

% 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)

我对稀疏矩阵操作不太熟悉,所以我可能会错过一个关键点,这可能会让我的代码大大加速。

我是否在代码中以合理的方式处理刚度矩阵的更新?还有另一种方法,我应该使用稀疏,这将导致更快的解决方案吗?

下面还提供了一个分析器报告: MATLAB Profiler Report

2 个答案:

答案 0 :(得分:3)

如果您只需要这些矩阵的总和,而不是单独构建所有矩阵然后对它们求和,只需连接向量IJvals并调用{{ 1}}只有一次。如果sparse中有重复的行[i,j],则相应的值[I,J]将自动相加,因此代码绝对等效。由于调用S(i,j)涉及对排序算法的内部调用,因此您可以保存13742-1中间类别,并且只能使用一个。


这涉及将sparse的签名更改为输出test_evaluate_stiffness

[I,J,val]

并删除第function [I,J,val] = test_evaluate_stiffness(n) 行。

然后,您将其他功能更改为:

out = sparse(I,J,val,n,n);

如果您提前知道n = 1000; [I,J,V] = deal([]); tic; for i = 1:13472 [I_i, J_i, V_i] = test_evaluate_stiffness(n); nE = numel(I_i); I(end+(1:nE)) = I_i; J(end+(1:nE)) = J_i; V(end+(1:nE)) = rand(1)*V_i; end K = sparse(I,J,V,n,n); fprintf('Stiffness Calculation Complete\nTime taken = %f s\n',toc); 输出的长度,可以通过适当地预先分配数组test_evaluate_stiffnessIJ来节省一些时间大小V矩阵并使用类似的东西设置它们:

zeros

答案 1 :(得分:0)

  

最大的剩余计算,耗时11秒,是稀疏操作   关于最终的IJV向量,所以我认为我们已将其归结为   骨头。

几乎......但最后一招:如果你可以创建向量以便J按升序排序,那么你将大大提高sparse调用的速度,大约是我的4倍经验。

(如果排序I更容易,则创建转置矩阵sparse(J,I,V)并在之后取消转置。)