scipy.sparse.linalg:spl和分解之间有什么区别?

viv*_*nov 5 numpy linear-algebra scipy sparse-matrix equation-solving

使用有什么区别

 scipy.sparse.linalg.factorized(A)
Run Code Online (Sandbox Code Playgroud)

 scipy.sparse.linalg.splu(A)
Run Code Online (Sandbox Code Playgroud)

它们都使用.solve(rhs)方法返回对象,并且文档中说它们都使用 LU 分解。我想知道他们两个的性能差异。

更具体地说,我正在编写一个实现动态 FEM 模型的 python/numpy/scipy 应用程序。我需要在每个时间步上求解方程Au = f。A 很稀疏而且相当大,但不依赖于时间步长,所以我想提前投入一些时间以使迭代更快(可能有数千次迭代)。我尝试使用scipy.sparse.linalg.inv(A),但是当矩阵大小很大时它会引发内存异常。直到最近我才使用scipy.linalg.spsolve每个步骤,现在正在考虑使用某种分解来获得更好的性能。所以,除了LU之外,如果你还有其他建议,欢迎提出!

twh*_*hes 3

A假设每个时间步长都不会改变,它们都应该可以很好地解决您的问题。

scipy.sparse.linalg.inv(A)将返回一个与 大小相同的密集矩阵A,因此它会抛出内存异常也就不足为奇了。

scipy.linalg.solve也是一个密集的线性求解器,这不是你想要的。

假设A稀疏,要解决Au=f并且您只想解决Au=f一次,您可以使用scipy.sparse.linalg.spsolve. 例如

u = spsolve(A, f)
Run Code Online (Sandbox Code Playgroud)

如果您想显着加快后续求解的速度,您可以使用scipy.sparse.linalg.factorizedor scipy.sparse.linalg.splu。例如

A_inv = splu(A)
for t in range(iterations):
    u_t = A_inv.solve(f_t)
Run Code Online (Sandbox Code Playgroud)

或者

A_solve = factorized(A)
for t in range(iterations):
    u_t = A_solve(f_t)
Run Code Online (Sandbox Code Playgroud)

它们的速度应该相当,并且比以前的选项快得多。

正如 @sascha 所说,您需要深入研究文档才能了解 slu 和 Factorize 之间的差异。但是,如果您已安装并正确设置,则可以使用“umfpack”代替默认的“superLU”。我认为 umfpack 在大多数情况下会更快。请记住,如果您的矩阵 A 太大或有太多非零值,则 LU 分解/直接求解器可能会占用系统上过多的内存。在这种情况下,您可能不得不使用像这样的迭代求解。不幸的是,您无法在每个时间步重用 A 的求解,但您也许能够为 A 找到一个好的预处理器(近似于 inv(A))来为求解器提供数据以加快其速度。