当A和B都是大矩阵时,在MATLAB中用AX = B求解X的有效方法

时间:2012-10-11 03:47:18

标签: matlab linear-algebra sparse-matrix factorization matrix-inverse

我遇到此问题需要在X中解决AX=BA的顺序为15000 x 15000,并且是稀疏且对称的。 B是15000 X 7500并且不稀疏。解决X的最快方法是什么?

我可以想到两种方式。

  1. 最简单的方式,X = A\B
  2. 使用for循环,

    invA = A\speye(size(A))
    for i = 1:size(B,2)
        X(:,i) = invA*B(:,i);
    end
    
  3. 有比上面两个更好的方法吗?如果不是,我提到的两者中哪一个最好?

4 个答案:

答案 0 :(得分:9)

首先要做的事情 - 永远,永远计算A的倒数。除非A是对角矩阵,否则永远不会稀疏。尝试使用简单的三对角矩阵。这条线本身会杀死你的代码 - 记忆方面和性能方面。并且计算逆数在数值上不如其他方法准确。

一般来说,\应该对你有用。 MATLAB确实认识到你的矩阵是稀疏的并且执行稀疏因子分解。如果给出矩阵B作为右侧,则性能比仅使用b向量求解一个方程组要好得多。所以你正确地做到了。您可以尝试的唯一其他技术问题是明确调用lucholldl,具体取决于您拥有的矩阵,并自行执行向后/向前替换。也许你在那里节省一些时间。

事实上,求解线性方程组的方法,特别是稀疏系统,很大程度上取决于问题。但在我想象的几乎任何(稀疏)情况下,15k系统的分解应该只需要几分之一秒。现在这不是一个大型系统。如果您的代码很慢,这可能意味着您的因素不再是稀疏稀疏。您需要确保矩阵正确重新排序,以便在稀疏分解期间最小化填充(添加的非零条目)。这是至关重要的一步。看看at this page有关如何重新排序系统的一些测试和解释。并简要介绍this SO thread处的示例重新排序。

答案 1 :(得分:3)

既然你可以回答自己哪一个更快,我会尝试你建议下一个选项。 使用GPU解决它。可以在线找到大量详细信息,包括SO post,A / b的matlab benchmarking等。 此外,还有LAMG(Lean Algebraic Multigrid)的MATLAB插件。 LAMG是一个快速图拉普拉斯算子。它可以在O(m)时间和存储中解决Ax = b。

答案 2 :(得分:2)

如果您的矩阵A是对称肯定的,那么您可以采取以下措施来有效和稳定地解决系统:

  • 首先,计算cholesky分解A=L*L'。由于你有一个稀疏矩阵,并且你想利用它来加速反演,你不应该直接应用chol,这会破坏稀疏模式。相反,使用here描述的重新排序方法之一。
  • 然后,按X = L'\(L\B)
  • 解决系统问题

最后,如果没有处理潜在的复杂值,那么你可以将所有L'替换为L.',这会进一步加速,因为它只是试图转置而不是计算复共轭。

另一种选择是Matlab中预处理的共轭梯度法pcg。这个在实践中非常流行,因为你可以通过速度来换取准确性,即减少迭代次数,它会给你一个(通常很好的)近似解决方案。您也永远不需要显式存储矩阵A,但只要能够使用A计算矩阵向量积,如果矩阵不适合内存。

答案 3 :(得分:1)

如果在测试中需要永远解决这个问题,那么您可能会进入虚拟内存进行求解。 15k方形(全)矩阵需要1.8千兆字节的RAM才能存储在内存中。

>> 15000^2*8
ans =
      1.8e+09

你需要一些严肃的RAM来解决这个问题,以及64位版本的MATLAB。除非你有足够的RAM来解决这个问题,否则没有因素分解会对你有帮助。

如果您的矩阵真的稀疏,那么您使用MATLAB的稀疏形式来存储它吗?如果没有,则MATLAB不知道矩阵是稀疏的,并且不使用稀疏因子分解。

A有多稀疏?许多人认为半满零的矩阵是“稀疏的”。那将浪费时间。在一个大小的矩阵上,你需要一个超过99%零的东西来真正从矩阵的稀疏因子分解中获得。这是因为填写。由此产生的分解矩阵几乎总是接近满。

如果你无法获得更多的RAM(你知道RAM是cheeeeeeeeee,当你考虑到你浪费时间试图解决这个问题的时候),那么你需要尝试一个迭代求解器。由于这些工具不会对矩阵进行分解,如果它真的很稀疏,那么它们就不会进入虚拟内存。这是一个巨大的节省。

由于迭代工具通常需要预处理器尽可能好地工作,因此可以通过一些研究来找到最佳的预处理器。