我有一个重复计算循环中稀疏矩阵的代码(它精确地执行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)
我对稀疏矩阵操作不太熟悉,所以我可能会错过一个关键点,这可能会让我的代码大大加速。
我是否在代码中以合理的方式处理刚度矩阵的更新?还有另一种方法,我应该使用稀疏,这将导致更快的解决方案吗?
下面还提供了一个分析器报告:
答案 0 :(得分:3)
如果您只需要这些矩阵的总和,而不是单独构建所有矩阵然后对它们求和,只需连接向量I
,J
和vals
并调用{{ 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_stiffness
,I
和J
来节省一些时间大小V
矩阵并使用类似的东西设置它们:
zeros
答案 1 :(得分:0)
最大的剩余计算,耗时11秒,是稀疏操作 关于最终的
I
,J
,V
向量,所以我认为我们已将其归结为 骨头。
几乎......但最后一招:如果你可以创建向量以便J
按升序排序,那么你将大大提高sparse
调用的速度,大约是我的4倍经验。
(如果排序I
更容易,则创建转置矩阵sparse(J,I,V)
并在之后取消转置。)