我遇到此问题需要在X
中解决AX=B
。 A
的顺序为15000 x 15000,并且是稀疏且对称的。 B
是15000 X 7500并且不稀疏。解决X的最快方法是什么?
我可以想到两种方式。
X = A\B
使用for循环,
invA = A\speye(size(A))
for i = 1:size(B,2)
X(:,i) = invA*B(:,i);
end
有比上面两个更好的方法吗?如果不是,我提到的两者中哪一个最好?
答案 0 :(得分:9)
首先要做的事情 - 永远,永远计算A的倒数。除非A是对角矩阵,否则永远不会稀疏。尝试使用简单的三对角矩阵。这条线本身会杀死你的代码 - 记忆方面和性能方面。并且计算逆数在数值上不如其他方法准确。
一般来说,\
应该对你有用。 MATLAB确实认识到你的矩阵是稀疏的并且执行稀疏因子分解。如果给出矩阵B
作为右侧,则性能比仅使用b
向量求解一个方程组要好得多。所以你正确地做到了。您可以尝试的唯一其他技术问题是明确调用lu
,chol
或ldl
,具体取决于您拥有的矩阵,并自行执行向后/向前替换。也许你在那里节省一些时间。
事实上,求解线性方程组的方法,特别是稀疏系统,很大程度上取决于问题。但在我想象的几乎任何(稀疏)情况下,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
是对称肯定的,那么您可以采取以下措施来有效和稳定地解决系统:
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,当你考虑到你浪费时间试图解决这个问题的时候),那么你需要尝试一个迭代求解器。由于这些工具不会对矩阵进行分解,如果它真的很稀疏,那么它们就不会进入虚拟内存。这是一个巨大的节省。
由于迭代工具通常需要预处理器尽可能好地工作,因此可以通过一些研究来找到最佳的预处理器。