我欢迎任何有关以下代码优化问题的帮助:
我有一组存储在单元格数组[s1 s2]
中的相同大小的N个稀疏矩阵(A
)以及存储在向量w
中的相应数量的标量权重。我想计算A
中所有矩阵的总和,加权w
中存储的值。通过我的程序的迭代,只有w
中的值发生了变化。因此,我可以先计算结果中非零元素的数量,并使用spalloc
为其预分配一些内存。
目前我有类似的东西:
result = spalloc(s1,s1,number_of_non_zero);
for i=1:N
result = result + w(i)*A{i};
end
我真的需要优化这个部分,暂时占用我程序中的大部分计算时间(使用剖析工具检查)。
一些额外的信息:
- 以上代码运行数百万次,因此即使是微小的改进也是值得欢迎的
- A
中的矩阵来自有限元素代码(1D或2D)
- 如果我可以节省一些时间(例如使用cell2mat(A)
)
感谢您提供有关如何加速这部分代码的任何提示。
一个。
答案 0 :(得分:1)
我不能确定这个解决方案是否会在计算上更有效率,但它还有其他的尝试......
如果你真的必须将你的矩阵表示为稀疏(即完整矩阵占用太多内存)并且MATLAB中的built-in sparse representation没有给你你想要的性能,那么你可以尝试表示稀疏矩阵以不同的方式。具体来说,您可以将它们表示为N×3矩阵,其中前两列包含所有非零值的矩阵中的行和列索引,第三列包含非零值。您可以使用函数FIND将数据转换为此表单,如下所示:
for iMatrix = 1:numel(A)
[r,c,v] = find(A{iMatrix});
A{iMatrix} = [r c v];
end
每次需要计算这些矩阵的加权和时,首先需要将这些值乘以权重:
B = A; %# Store a temporary copy of A
for iMatrix = 1:numel(B)
B{iMatrix}(:,3) = w(iMatrix).*B{iMatrix}(:,3);
end
然后,您可以使用函数ACCUMARRAY计算最终总和:
B = vertcat(B{:}); %# Convert B from a cell array to an N-by-3 matrix
result = accumarray(B(:,1:2),B(:,3));
在这种情况下,变量result
将是一个完整的矩阵。如果您需要result
作为稀疏矩阵,则可以在ACCUMARRAY的调用中添加额外的参数,如下所示:
result = accumarray(B(:,1:2),B(:,3),[],[],[],true);
答案 1 :(得分:0)
如果将A
转换为矩阵而不是单元格数组,则可以使用某些RESHAPE和REPMAT杂技来对循环进行矢量化。假装我们有以下数据:
>> A(:,:,1) = [1 0 0; 0 0 2; 0 0 0]; >> A(:,:,2) = [3 0 1; 0 3 0; 0 1 0] A(:,:,1) = 1 0 0 0 0 2 0 0 0 A(:,:,2) = 3 0 1 0 3 0 0 1 0 >> w = [2; 3] w = 2 3
重新塑造w
,以便您可以逐个元素进行乘法,然后求和:
>> w = reshape(w, [1 1 length(w)]) w(:,:,1) = 2 w(:,:,2) = 3 >> w = repmat(w, [size(A,1) size(A,2) 1]) w(:,:,1) = 2 2 2 2 2 2 2 2 2 w(:,:,2) = 3 3 3 3 3 3 3 3 3 >> w .* A ans(:,:,1) = 2 0 0 0 0 4 0 0 0 ans(:,:,2) = 9 0 3 0 9 0 0 3 0 >> sum(w .* A, 3) ans = 11 0 3 0 9 4 0 3 0