加速稀疏矩阵计算

时间:2013-05-12 16:05:15

标签: performance matlab sparse-matrix

是否有可能通过例如加速大型稀疏矩阵计算。最佳地放置parantheses?

我要问的是:我可以通过强制Matlab以指定顺序执行操作来加速以下代码(例如“从右到左”或类似的东西)?

我有一个稀疏的方形对称矩阵H,它先前已被分解,还有一个稀疏向量M,其长度等于H的维数。我想做的是以下内容:

编辑:一些其他信息:H通常为4000x4000。 z和c的计算大约进行了4000次,而dVa和dVaComp的计算每4000次循环进行10次,总计40000次。 (dVa和dVaComp迭代求解,其中P_mis被更新)。

这里M*c*M'将成为具有4个非零元素的稀疏矩阵。在Matlab中:

[L U P] = lu(H);                 % H is sparse (thus also L, U and P)
% for i = 1:4000             % Just to illustrate
M = sparse([bf bt],1,[1 -1],n,1);  % Sparse vector with two non-zero elements in bt and bf
z = -M'*(U \ (L \ (P * M)));     %  M^t*H^-1*M = a scalar
c = (1/dyp + z)^-1;              % dyp is a scalar
  % while (iterations < 10 && ~=converged)
    dVa = - (U \ (L \ (P * P_mis))); 
    dVaComp = (U \ (L \ (P * M * c * M' * dVa)));
    % Update P_mis etc. 
  % end while
% end for

并且为了记录:尽管我多次使用H的倒数,但预先计算它并不快。

谢谢=)

2 个答案:

答案 0 :(得分:1)

在对(稀疏)矩阵lu进行分解时,您可能想尝试使用H的扩展语法:

[L,U,P,Q] = lu(H);

额外排列矩阵Q重新排序列以增加因子L,U的稀疏性(而排列矩阵P仅重新排序行以进行部分旋转)。

具体结果取决于H的稀疏模式,但在许多情况下使用良好的列排列显着会减少因子分解中的非零数量,从而减少内存使用并增加速度。

您可以详细了解lu语法here

答案 1 :(得分:1)

有些事情对我来说并不完全清楚:

  • 命令M = sparse([t f],[1 -1],1,n,1);不能正确;你在行t,f和列1,-1上说的应该是1;专栏-1显然不对。
  • 结果dVaComp是一个完整的矩阵,因为乘以P_mis,而你说它应该是稀疏的。

暂时搁置这些问题,我看到了一些小优化:

  • 您使用inv(H)*M两次,因此您可以预先计算它。
  • dVa的否定可以移出循环。
  • 如果您不明确需要dVa,请将分配遗漏给变量。
  • 标量的反转意味着将1除以该标量(c的计算)。

实施更改,并尝试公平比较(我只使用了40次迭代以保持总时间很短):

%% initialize
clc
N = 4000;

% H  is sparse, square, symmetric
H = tril(rand(N));
H(H<0.5) = 0; % roughly half is empty
H = sparse(H+H.');

% M is sparse vector with two non-zero elements.
M = sparse([1 N],[1 1],1, N,1);

% dyp is some scalar
dyp = rand;

% P_mis = full vector
P_mis = rand(N,1);


%% original method

[L, U, P] = lu(H);   

tic             

for ii = 1:40

    z = -M'*(U \ (L \ (P*M)));
    c = (1/dyp + z)^-1;

    for jj  = 1:10        
        dVa = -(U \ (L \ (P*P_mis)));
        dVaComp = (U \ (L \ (P*M * c * M' * dVa)));    
    end

end

toc


%% new method I

[L,U,P,Q] = lu(H);    

tic            

for ii = 1:40

    invH_M = U\(L\(P*M));

    z = -M.'*invH_M;
    c = -1/(1/dyp + z);

    for jj = 1:10          
        dVaComp = c * (invH_M*M.') * ( U\(L\(P*P_mis)) );
    end 

end

toc

这给出了以下结果:

Elapsed time is 60.384734 seconds. % your original method
Elapsed time is 33.074448 seconds. % new method