我有这个问题,需要在AX=B
中解决X
。CCD_ 3的数量级为15000x15000并且是稀疏和对称的。B
是15000 X 7500并且不是稀疏的。求解X的最快方法是什么?
我能想出两种方法。
- 最简单的方法,
X = AB
-
用于环路,
invA = Aspeye(size(A)) for i = 1:size(B,2) X(:,i) = invA*B(:,i); end
有比以上两种更好的方法吗?如果不是,在我提到的两者中,哪一个最好?
首先计算A的逆。这是never稀疏的,除非A是对角矩阵。尝试一下简单的三对角矩阵。这一行本身就扼杀了代码的内存和性能。而且,在数值上计算逆的精度不如其他方法。
一般来说,应该对你很好。MATLAB确实认识到您的矩阵是稀疏的,并执行稀疏因子分解。如果将矩阵
B
作为右侧,则性能比仅使用b
向量求解一个方程组要好得多。所以你做得对。这里唯一可以尝试的其他技术是显式调用lu
、chol
或ldl
,具体取决于您所拥有的矩阵,并自己执行后向/前向替换。也许你可以在那里节省一些时间。
事实上,求解线性方程组,特别是稀疏方程组的方法在很大程度上取决于这个问题。但在我想象的几乎任何(稀疏)情况下,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很俗气,当然,一旦你考虑到你在解决这个问题上浪费了时间),那么你就需要尝试迭代求解器。由于这些工具不会分解矩阵,如果它真的很稀疏,那么它们就不会进入虚拟内存。这是一笔巨大的节省。
由于迭代工具通常需要一个预处理器尽可能好地工作,因此可能需要一些研究才能找到最好的预处理器。