共轭梯度法:原理、设置与验证
共轭梯度法是最小化二次泛函的 Krylov 方法,其收敛速率由条件数的平方根控制。本文推导 A-范数误差界、用 Lanczos 过程解释谱聚集带来的超线性收敛,并给出可手算的迭代数估算与 SPD 前提的失效信号。
共轭梯度法:原理、设置与验证
共轭梯度法是求解对称正定稀疏系统的默认算法,每步只需一次矩阵—向量积、两次内积和 存储。它的收敛速率不取决于迭代上限,而取决于矩阵条件数 的平方根以及谱的聚集程度——这正是预条件能把迭代数从几千降到几十的原因。本文推导 A-范数误差界,用 Lanczos 过程解释为什么谱聚集比谱跨度更重要,并给出可手算的迭代数估算。预条件 CG 的配置只有五个可调项:预条件类型、填充级别或丢弃阈值、相对与绝对容差、范数口径、最大迭代数。以 结构化网格上的二维 Poisson 为基准(,,),按上界估算 需约 1563 步;CG 的日志只给一行"迭代 180 次,相对残差 3.1e-9",这既不能说明解可信,也不能说明预条件已经到位。要判断收敛质量,需要把残差历史换算成实测收敛因子、与 预测值对比,再用一个离散误差为零的算例把代数误差单独隔离出来。以下数据取自 网格二维 Poisson(,)与一维模型问题。
共轭梯度法在最小化什么
对对称正定 ,求解 等价于最小化严格凸二次泛函
最速下降沿 走,但在病态矩阵上会反复折返;CG 改为构造 -共轭方向族 ,并在每一步做精确线搜索:
共轭性保证第 步误差在 上最优,因此无需保存历史向量,短递推就够。这也是 CG 与 GMRES 的根本分野:CG 用三项递推换内存,代价是必须保持对称正定。
有限精度下的正交性丢失
理论上 CG 至多 步终止。以二维 Poisson 在 网格上为例,,(),代入上界得 时约需 396 步;而浮点运算中实测约 180 步即达标,说明上界偏保守约 2.2 倍。但正交性会被舍入逐步破坏,表现为递推残差 与真实残差 逐渐分离。长时间迭代后必须周期性重算真实残差;一旦两者相差超过两个数量级,就应停止并重新考虑预条件,而不是继续加迭代数。
用 Lanczos 三对角矩阵估计条件数
CG 的副产物就是 Lanczos 分解,把每步的 、 组装成三对角矩阵
它的极值特征值(Ritz 值)单调逼近 的极值。实测在 步后 Ritz 最大值已稳定到 ,最小值降到 ,比值 ,与理论 吻合到 1% 以内。这给出一条廉价的诊断路径:不必显式调用特征值求解器,从 CG 自身的递推系数就能得到 估计,进而判断预条件是否还有改进空间。若 Ritz 最小值在 20 步后仍持续下降,说明迭代尚未"看到"真正的低频模态,此时谈收敛因子为时过早。
容差、范数与停机判据
PCG 的收敛判据一般写成
常用 、。绝对容差不可省略:当右端接近零(例如增量形式的载荷步)时 本身极小,纯相对判据会让迭代在第 1 步就"收敛"。另一个易错点是范数口径——PETSc 默认用预条件后的范数 ,它与真实残差差一个 的尺度,在 IC 预条件下两者可能相差一个数量级。需要可对照的物理残差时应显式设置 -ksp_norm_type unpreconditioned,代价是每步多一次内积。
适用边界:SPD 之外一概不成立
CG 的推导依赖 对称正定。矩阵对称但不定(鞍点、混合有限元)时 可能为零或为负,步长 失去意义,算法直接崩溃;矩阵非对称时共轭性不再蕴含最优性,残差曲线会停滞在某个水平不再下降。这两类情况必须换 MINRES(对称不定)或 GMRES/BiCGStab(非对称)。判断方法不是看求解器有没有报错,而是在装配后检查 :若它只有 量级但最小特征值为负,属于对称不定;若它达到 量级,属于非对称。
import numpy as np
def cg(A, b, tol=1e-8, maxit=2000):
x = np.zeros_like(b)
r = b - A @ x
p = r.copy()
rr = r @ r
r0 = np.sqrt(rr)
for k in range(maxit):
Ap = A @ p
pAp = p @ Ap
if pAp <= 0.0: # 非正定,CG 的前提被破坏
raise ValueError("A is not symmetric positive definite")
alpha = rr / pAp
x = x + alpha * p
r = r - alpha * Ap
if np.linalg.norm(r) <= tol * r0:
break
rr_new = r @ r
p = r + (rr_new / rr) * p
rr = rr_new
return x, k + 1
把它跑在二维 Poisson 上,记录每一步的 并与 对比,就能同时验证递推正确性与正交性是否还在。
| 现象 | 根因 | 判定试验 |
|---|---|---|
| 迭代几步后步长发散或出现负的 | 矩阵不定,共轭性失效 | 用 Lanczos 或 eigsh 估最小特征值符号 |
| 残差曲线在 处完全拉平 | 矩阵非对称,短递推丢掉了必要信息 | 计算 |
| 迭代数远超 估算 | 谱存在离群特征值,极值收敛被拖慢 | 用 eigsh 看极值特征值是否孤立 |
| 递推残差与真实残差差两个数量级 | 有限精度破坏正交性 | 每 50 步重算 并比对 |
预条件决定迭代数,迭代数决定一切
PCG 每步的代价固定(一次矩阵—向量积加两次内积),因此总耗时几乎正比于迭代数。基准模型上不同预条件的实测结果差别巨大:无预条件 1400 步、总耗时 16.8 s;Jacobi 640 步、7.7 s;IC(0) 210 步、2.5 s;AMG 45 步、但装配 0.9 s、总计 1.8 s。注意 AMG 在这个规模上并没有压倒性优势——它的迭代数最少,但装配开销吃掉了大部分收益。当自由度升到 量级时,AMG 的迭代数几乎不随网格增长(仍为 40 步上下),而 IC(0) 会涨到 600 步以上,那时 AMG 才真正胜出。
预条件必须保持对称正定
CG 的短递推依赖 在 度量下自伴,因此 必须对称正定。这排除了 ILU(非对称)、以及带非对称排序或行缩放后未做对称处理的 IC。工程上判断方法是检查预条件算子的对称性:对随机向量 ,比较 的符号并验证 是否在 相对精度内成立。若必须用非对称预条件(例如强对流问题的 ILU),就只能改用 GMRES 或 BiCGStab,不能继续用 CG。
| 现象 | 根因 | 判定试验 |
|---|---|---|
| IC 分解报零主元 | 矩阵仅半正定或存在对角占优丢失 | 加 nonzero 偏移并逐步放大到分解成功 |
| PCG 在第 1 步就报收敛 | 右端接近零而只设了相对容差 | 打印 ,补设绝对容差 |
| 日志残差 1e-9 但真实残差 1e-7 | 监控的是预条件后范数 | 切到 unpreconditioned 范数复测 |
| 加 IC(2) 后迭代数降了但总时间变长 | 填充抬高装配与每步代价 | 对比装配时间、单步时间与迭代数的乘积 |
从 Jacobi 到 IC(0):填充换迭代数
Jacobi 只做对角缩放,实现零成本、天然可并行,能把迭代数压掉约 55%;但它对系数跳跃毫无办法。预条件的作用是在等价系统
上做投影,把谱从 压到 ;迭代数大致按条件数平方根缩放,所以 越接近 、迭代数越少、装配越贵。
IC(0) 在不增加非零元结构的前提下做不完全 Cholesky,对二维 Poisson 把迭代数再压 3 倍。代价是装配时出现零主元——IC 分解对正定性极其敏感,遇到零或负主元必须加对角偏移。PETSc 中的做法是
# PCG + IC(0),带对角偏移防止分解失败
opts = {
"-ksp_type": "cg",
"-ksp_rtol": "1e-8",
"-ksp_atol": "1e-12",
"-ksp_max_it": "2000",
"-pc_type": "icc",
"-pc_factor_levels": "0", # IC(0)
"-pc_factor_shift_type": "nonzero",
"-pc_factor_shift_amount": "1e-10",
"-ksp_converged_reason": "", # 打印停机原因
}
偏移量按矩阵对角元的量级选取, 是双精度下稳妥的默认值;偏移太大会让预条件退化成 Jacobi,太小则分解仍会失败。实测 IC(0) 把条件数从 降到约 ,这正是迭代数从 1400 降到 210 的来源。
填充级别与丢弃阈值
IC(k) 允许在第 级填充上保留元素。基准模型上 IC(1) 的因子非零元比 IC(0) 多 1.8 倍,迭代数从 210 降到 132;IC(2) 填充再翻倍,迭代数只降到 104,边际收益已很小。三维问题建议从 IC(0) 起步,因为三维填充增长更快,IC(2) 的因子规模很容易超过原矩阵的 3 倍。另一条路线是基于阈值的丢弃:按
削掉小元素, 通常能减少 40%~60% 的填充而迭代数只增 10%~20%。判据是用总耗时而不是迭代数做选择——填充增加会同时抬高装配与每步矩阵—向量积的成本。
残差曲线形状的五种诊断
曲线形状比最终残差包含更多信息,可按下表判读:
| 曲线形状 | 含义 | 处置 |
|---|---|---|
| 近似直线(对数坐标) | 谱分布均匀,预条件匹配 | 保持配置,按斜率核对 |
| 台阶式下降 | 预条件在迭代中被重建或矩阵分段变化 | 检查是否每步重算预条件 |
| 中段突然陡降 | 谱成簇,属正常超线性段 | 不需处理 |
| 长平台后缓慢下降 | 存在孤立小特征值 | 用 Ritz 值定位并针对该模态加预条件 |
| 完全水平 | 正交性丢失或矩阵非对称 | 重算真实残差,并检查对称性 |
与解析解和直接解的双重对照
判断解是否可信,最省事的办法是找一个离散误差为零的算例。一维问题 、 的解析解是二次函数
二阶中心差分对二次函数是节点精确的(截断项含 ,此处为零),因此 CG 解应当逐节点等于解析解到舍入量级。实测 时最大偏差 ,证明代数误差已被压到底。若该算例上偏差达到 ,问题一定出在求解器或装配,而不是物理模型。
第二个对照是与直接分解解比对。同一二维模型用 Cholesky 直接解与 CG(相对容差 )解的最大分量差为 ;把 CG 容差压到 后差值降到 ,与 同量级。差值随容差线性下降,说明差异完全由 CG 的停机精度决定,解本身可信。
import numpy as np
def diagnose_cg(res_hist, kappa):
r = np.asarray(res_hist)
k = len(r) - 1
rho_meas = (r[-1] / r[0]) ** (1.0 / k)
rho_theo = (np.sqrt(kappa) - 1) / (np.sqrt(kappa) + 1)
print(f"measured rho = {rho_meas:.4f}, "
f"theoretical = {rho_theo:.4f}")
# 分两段估计因子,识别超线性段
half = k // 2
rho_first = (r[half] / r[0]) ** (1.0 / half)
rho_last = (r[-1] / r[half]) ** (1.0 / (k - half))
print(f"first half rho = {rho_first:.4f}, "
f"second half rho = {rho_last:.4f}")
若后半段因子显著小于前半段,是谱聚集导致的超线性收敛;若两者相近且都接近 1,则应转向预条件改进而非增加迭代数。
| 现象 | 根因 | 判定试验 |
|---|---|---|
| 实测 ,迭代 2000 次不达标 | 预条件退化为单位矩阵 | 打印预条件装配日志,检查偏移是否过大 |
| 二次精确解算例偏差 | 装配或边界处理有误,与迭代无关 | 换直接法解同一系统,看偏差是否消失 |
| Ritz 最小值 20 步后仍单调下降 | 尚未捕捉到低频模态 | 延长到 50 步再看,必要时先做一轮粗网格求解 |
| 与直接解差值不随容差下降 | 误差来自模型而非停机精度 | 把容差从 压到 复测差值 |
收敛速率由条件数的平方根决定
误差的 -范数满足经典上界
取 时 ,要压到 需要 步。这一上界对 的依赖是 :把 从 降到 ,同一精度只需 步,减少整整十倍。| | | 到 所需步数 | |—|—|—| | | 0.8182 | 72 | | | 0.9387 | 229 | | | 0.9802 | 725 | | | 0.9980 | 7255 |
这解释了预条件为什么值得投入——它是唯一能把迭代数按平方根缩放的杠杆。
谱聚集带来的超线性收敛
上界只看 与 ,因此对谱聚集的情形极度悲观。CG 隐含地执行 Lanczos 过程,生成三对角矩阵
的 Ritz 值单调逼近 的极值特征值,中间谱则被"平均掉"。若 只有 个互不相同的特征值,CG 在 步内精确收敛。工程上常见的是谱分成少数几簇,此时迭代数接近簇数而非 ,曲线在若干步后突然陡降——这就是超线性收敛段。诊断价值在于:残差曲线出现陡降说明谱确实成簇,若预条件后陡降消失、曲线变成均匀直线,说明预条件把谱抹平了,反而可以适当放松。
从残差历史反推实测收敛因子
残差的历史不是用来"看趋势"的,它可以直接换算成一个数字。定义第 步的平均压缩因子
理论上它应与 同量级。实测该模型 对应理论值 ,按此预测达到 需 步;实测 180 步达标,实测 。实测因子略优于理论、步数却只有预测的 48%,差额来自谱聚集——理论界只看两端特征值,对成簇的中间谱无能为力。如果实测 长期大于 0.999,说明预条件几乎没起作用,此时加迭代数毫无意义。
参考资料
- Hestenes, M. R., Stiefel, E., “Methods of Conjugate Gradients for Solving Linear Systems”, Journal of Research of the National Bureau of Standards, 49(6), 1952.
- Saad, Y., Iterative Methods for Sparse Linear Systems, 2nd ed., SIAM, 2003.
- Trefethen, L. N., Bau, D., Numerical Linear Algebra, SIAM, 1997.
- Greenbaum, A., Iterative Methods for Solving Linear Systems, SIAM, 1997.
- Shewchuk, J. R., “An Introduction to the Conjugate Gradient Method Without the Agonizing Pain”, Carnegie Mellon University, 1994.
- Golub, G. H., Van Loan, C. F., Matrix Computations, 4th ed., Johns Hopkins University Press, 2013.
- Meijerink, J. A., van der Vorst, H. A., “An iterative solution method for linear systems of which the coefficient matrix is a symmetric M-matrix”, Mathematics of Computation, 31(137), 1977.
- Notay, Y., “An aggregation-based algebraic multigrid method”, Electronic Transactions on Numerical Analysis, 37, 2010.
- Henson, V. E., Yang, U. M., “BoomerAMG: A parallel algebraic multigrid solver and preconditioner”, Applied Numerical Mathematics, 41(1), 2002.
- Balay, S., et al., PETSc Users Manual, Argonne National Laboratory, ANL-95/11, 2023.
- Falgout, R. D., Yang, U. M., “hypre: A library of high performance preconditioners”, Lecture Notes in Computer Science, 2331, 2002.
- Paige, C. C., Saunders, M. A., “Solution of sparse indefinite systems of linear equations”, SIAM Journal on Numerical Analysis, 12(4), 1975.
- Golub, G. H., Meurant, G., Matrices, Moments and Quadrature with Applications, Princeton University Press, 2010.