第3章 线性代数与稀疏计算 章节摘要:线性方程组的求解是科学计算里出现频率最高的数值操作,但矩阵规模一上来,问题就变了性质——百万未知数的方程组,稠密存储根本装不进内存,传统分解算法的耗时也超出耐心。本章先讲清 scipy.linalg 相对 numpy.linalg 多了什么:更完整的分解家族、带假设检查的求解接口、矩阵函数;再讲 scipy.sparse 的 COO、CSR、CSC 三种主力格式与 cg、gmres 迭代求解器,回答"什么时候值得用稀疏";最后用有限差分离散的二维泊松方程做实战,把稠密与稀疏两条路线放在同一台机器上比内存、比耗时,让你对规模之墙在哪里、怎么绕过去,有一个具体的体感。
章节摘要:线性方程组的求解是科学计算里出现频率最高的数值操作,但矩阵规模一上来,问题就变了性质——百万未知数的方程组,稠密存储根本装不进内存,传统分解算法的耗时也超出耐心。本章先讲清 scipy.linalg 相对 numpy.linalg 多了什么:更完整的分解家族、带假设检查的求解接口、矩阵函数;再讲 scipy.sparse 的 COO、CSR、CSC 三种主力格式与 cg、gmres 迭代求解器,回答"什么时候值得用稀疏";最后用有限差分离散的二维泊松方程做实战,把稠密与稀疏两条路线放在同一台机器上比内存、比耗时,让你对规模之墙在哪里、怎么绕过去,有一个具体的体感。学完本章,你既能在小规模问题上用直接法快速出数,也能在大规模问题上从容设计存储方案与求解路线。

阅读完本章,你应当能够:
一句话点题:稠密路线吃内存,稀疏路线吃迭代次数,选哪条路先看非零占比。
从一段能跑的代码出发,对比 scipy.linalg 与 numpy.linalg 的功能边界。LU、Cholesky、QR、SVD 四种分解的适用条件与代码写法,solve 的假设检查参数,条件数与病态矩阵的误差放大机理,以及 expm、sqrtm 这类矩阵函数的正确用法,都在这一节落地。这一节回答的问题是:矩阵不大、可以稠密存储时,怎么把求解做到又快又稳。
回答"什么时候值得用稀疏":非零占比低到多少、规模大到多少才划算。COO、CSR、CSC 的存储结构、构建与转换,稀疏矩阵乘向量的性能来源,sparse.linalg 里 cg、gmres 迭代求解器的用法,预条件为何能把迭代次数压下一个数量级,以及 eigs 如何只算少数几个特征值。这一节回答的问题是:矩阵大到装不下时,怎么换一套存法和算法。
把二维泊松方程用五点差分离散成五对角稀疏矩阵,在同一台机器上分别走稠密与稀疏两条求解路线,从 50 乘 50 网格一路推到 1000 乘 1000,实测内存与耗时差异,并检验解的精度。这一节是前两节知识的汇合点,也是你以后处理偏微分方程数值问题的起步模板。这一节回答的问题是:两条路线在同题竞技中,差距到底有多大。
本章的推进逻辑是"先摸清稠密路线的天花板,再认识稀疏路线,最后同场对比":
矩阵规模小:3.1 稠密路线 │ 矩阵变大、非零占比下降 ▼ 规模大到装不下:3.2 稀疏路线 │ 同一个问题、两种实现 ▼ 3.3 实战:泊松方程同场对比
3.1 建立的分解、条件数与矩阵函数直觉,是判断"直接法还扛不扛得住"的依据;3.2 给出的存储格式与迭代求解器,是绕过内存墙的路线图;3.3 把两套工具装进同一个真实问题,用实测数字验证前面两节的判断。三节合起来回答一个完整的问题:一个大规模线性系统,到底该怎么存、怎么解、为什么。注意 3.2 里的 diags 构造法在 3.3 里直接复用,3.1 的条件数概念在 3.2 的预条件讨论里再次出现——三条知识线在实战节收束成一条。换句更直白的说法:3.1 教你在小矩阵上把每一分计算都用足,3.2 教你在大矩阵上把每一分内存都省下,3.3 则告诉你这两套本事在同一个问题上以哪里为分界。