使用矢量化求解多个线性系统

时间:2011-06-14 14:05:19

标签: matlab linear-algebra

很抱歉,如果这是显而易见的,但我搜索了一段时间,没有找到任何东西(或错过了它)。

我正在尝试使用 A 4x4矩阵来解决 Ax = B 形式的线性系统,并且 B 一个4x1向量。

我知道对于单个系统,我可以使用mldivide来获取 x x=A\B

但是我试图解决大量系统(可能> 10000)并且我不愿意使用for循环因为我被告知它在许多MATLAB问题中比矩阵公式慢得多。

我的问题是:有没有办法解决 Ax = B 使用 A 4x4x N B <进行矢量化/ em>矩阵4x N

PS:我不知道它是否重要,但 B 向量对于所有系统都是相同的。

5 个答案:

答案 0 :(得分:5)

你应该使用for循环。如果A保持不变并且B更改,则预先计算分解并重新使用它可能会有好处。但对于A更改且B保持不变的问题,除了解决N个线性系统之外别无选择。

你不应该过多担心循环的性能成本:MATLAB JIT compiler意味着在最近的MATLAB版本中循环通常也一样快。

答案 1 :(得分:5)

我认为你不能进一步优化这一点。正如@Tom所解释的那样,由于A是一个变化,因此预先考虑各种A是没有好处的......

除了你提到的尺寸外,循环解决方案非常快:

A = rand(4,4,10000);
B = rand(4,1);          %# same for all linear systems

tic
X = zeros(4,size(A,3));
for i=1:size(A,3)
    X(:,i) = A(:,:,i)\B;
end
toc
  

经过的时间是0.168101秒。

答案 2 :(得分:3)

这是问题所在: 您正尝试在3d矩阵上执行2D操作(mldivide)。无论你如何看待它,你都需要通过索引来引用矩阵,这就是时间惩罚的开始......这不是for循环的问题,而是人们如何使用它们。 如果你能以不同的方式构建你的问题,那么也许你可以找到一个更好的选择,但是现在你有几个选择:

1 - mex

2 - 并行处理(写一个parfor循环)

3 - CUDA

答案 3 :(得分:3)

这是一个相当深奥的解决方案,它利用了MATLAB的独特优化。使用对角线下方的4x4块构建一个巨大的4k x 4k 稀疏矩阵。然后同时解决所有问题。

在我的机器上,与@ Amro / Tom的for-loop解决方案相比,它获得了与单精度精度相同的解决方案,但速度更快。

n = size(A,1);
k = size(A,3);
AS = reshape(permute(A,[1 3 2]),n*k,n);
S = sparse( ...
  repmat(1:n*k,n,1)', ...
  bsxfun(@plus,reshape(repmat(1:n:n*k,n,1),[],1),0:n-1), ...
  AS, ...
  n*k,n*k);
X = reshape(S\repmat(B,k,1),n,k);

随机示例:

For k = 10000
For loop: 0.122570 seconds.
Giant sparse system: 0.032287 seconds.

如果你知道你的4x4矩阵是肯定的,那么你可以在S上使用chol来提高准确性。

这是愚蠢的。但是,即使使用JIT,2015年matlab的循环仍然的速度有多慢。当k不是太大时,这个解决方案似乎找到了一个最佳点,因此一切仍然适合记忆。

答案 4 :(得分:2)

我知道这篇文章已经有好几年了,不管怎么说,我还是会贡献两分钱。您可以将所有A矩阵放入更大的块对角矩阵中,在大矩阵的对角线上将有4x4块。右手边将是你的所有b向量一遍又一遍地堆叠在一起。一旦你设置了它,它就被表示为一个稀疏系统,可以用mldivide选择的算法有效地解决。这些块在数值上是分离的,所以即使在那里有奇异的块,当你使用mldivide时,非奇异块的答案应该是正确的。有一个代码在MATLAB Central上采用了这种方法:

http://www.mathworks.com/matlabcentral/fileexchange/24260-multiple-same-size-linear-solver

我建议尝试查看方法是否比循环更快。我怀疑它可以更有效,特别是对于大量的小型系统。特别是,如果在N个矩阵中有一个很好的A系数公式,你可以使用MATLAB向量运算(无需循环)构建完整的左侧,这可以为您节省额外的成本。正如其他人所指出的那样,矢量化操作并不总是更快,但它们通常都符合我的经验。