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



我有这个问题,需要在AX=B中解决X。CCD_ 3的数量级为15000x15000并且是稀疏和对称的。B是15000 X 7500并且不是稀疏的。求解X的最快方法是什么?

我能想出两种方法。

  1. 最简单的方法,X = AB
  2. 用于环路,

    invA = Aspeye(size(A))
    for i = 1:size(B,2)
    X(:,i) = invA*B(:,i);
    end
    

有比以上两种更好的方法吗?如果不是,在我提到的两者中,哪一个最好?

首先计算A的逆。这是never稀疏的,除非A是对角矩阵。尝试一下简单的三对角矩阵。这一行本身就扼杀了代码的内存和性能。而且,在数值上计算逆的精度不如其他方法。

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

事实上,求解线性方程组,特别是稀疏方程组的方法在很大程度上取决于这个问题。但在我想象的几乎任何(稀疏)情况下,15k系统的因子分解应该只需要几分之一秒。如今,这不是一个大系统。如果你的代码很慢,这可能意味着你的因子不再那么稀疏了。您需要确保矩阵被正确地重新排序,以在稀疏因子分解过程中最小化填充(添加的非零项)。这是至关重要的一步。请查看此页面,了解有关如何重新排序系统的一些测试和解释。并简要地看一下这个SO线程中的示例重新排序。

由于您可以自己回答两者中哪一个更快,我将尝试建议下一个选项。使用GPU解决问题。很多细节可以在网上找到,包括这篇SO帖子,a/b的matlab基准测试,等等。此外,还有LAMG(Lean Algebraic Multigrid)的MATLAB插件。LAMG是一个快速的图拉普拉斯解算器。它可以在O(m)时间和存储中求解Ax=b。

如果你的矩阵A是对称正定的,那么你可以做些什么来高效稳定地求解系统:

  • 首先,计算cholesky分解A=L*L'。由于你有一个稀疏矩阵,并且你想利用它来加速反演,所以你不应该直接应用chol,这会破坏稀疏性模式。相反,请使用此处描述的重新排序方法之一
  • 然后,用X = L'(LB)对系统进行求解

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

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

如果这在测试中需要很长时间才能解决,那么您可能会进入虚拟内存进行解决。一个15k平方(完整)的矩阵需要1.8G的RAM才能存储在内存中。

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

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

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

A有多稀疏?许多人认为半满零的矩阵是"稀疏的"。那将是浪费时间。在这样大小的矩阵上,你需要远远超过99%的零才能真正从矩阵的稀疏因子分解中获得好处。这是因为填充。否则,得到的因子分解矩阵几乎总是几乎满的。

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

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

最新更新