应优先使用 torch.linalg.svd,因 PyTorch 2.0+ 中 torch.svd 已弃用并指向它,但需注意返回值差异:torch.linalg.svd 默认返回 (U, S, Vh),其中 Vh 是 V 的共轭转置,而旧 torch.svd 返回 (U, S, V),直接替换需改为 V = Vh.mH 以保持兼容。

torch.linalg 不是独立子模块,它是 PyTorch 2.0+ 中统一的线性代数接口,取代了旧版 torch.symeig、torch.qr 等分散函数。想加速矩阵分解,关键不是“用哪个子模块”,而是选对函数、配对硬件、避开隐式拷贝。
该用 torch.linalg.svd 还是 torch.svd?
PyTorch 2.0 起,torch.svd 已弃用并指向 torch.linalg.svd,但行为不完全兼容:
- torch.linalg.svd 默认返回 (U, S, Vh),且 Vh 是共轭转置(符合 NumPy 和数学惯例)
- 旧 torch.svd 返回 (U, S, V),V 是未转置的右奇异向量
- 若代码依赖 V 而非 Vh,直接替换会出错,需改成 V = Vh.mH
为什么 GPU 上 torch.linalg.svd 有时比 CPU 还慢?
这不是 bug,而是 cuSOLVER 的实际限制:
- 小矩阵(如 100x100)在 GPU 上启动开销远大于计算收益
- torch.linalg.svd 在 CUDA 上仅支持 float32 和 float64,float16 会自动升到 float32,反而增加显存和带宽压力
- 某些驱动 + CUDA 版本组合下,cuSOLVER 的 batched SVD 实现有性能回退(尤其 Ampere 架构前)
实操建议:
- 矩阵尺寸 torch.linalg.svd(..., device="cpu"))
- 必须用 GPU 时,确保输入已位于 GPU 且 dtype 显式设为 torch.float32
- 批处理多矩阵?用 torch.linalg.svd 的 batched 输入(3D 张量),别写 for 循环
Cholesky 分解加速:为什么 torch.linalg.cholesky 报 “not positive definite”?
这不是精度问题,而是输入检查更严格了:
- torch.linalg.cholesky 默认启用 upper=False 且要求矩阵严格正定
- 即使数值上接近正定(如协方差矩阵含微小负特征值),也会报错,而旧 torch.cholesky 可能静默容忍
解决方法:
- 先用 torch.linalg.eigvalsh 检查最小特征值:eig_min = torch.linalg.eigvalsh(A).min()
- 若 eig_min ,加一个小单位阵扰动:<code>A = A + 1e-8 * torch.eye(A.size(0), device=A.device)
- 或改用 torch.linalg.cholesky_ex,它返回 success flag,便于 fallback 处理
分解结果没变快?检查这三件事
加速失效往往卡在数据流转环节:
- 输入张量不是 contiguous:调用前加 A = A.contiguous(),否则 torch.linalg 内部会拷贝
- 混用设备:确保所有参与运算的张量(包括中间缓存)在同一 device,A.to("cuda") 不等于 A.cuda(),后者可能触发隐式流同步
- autograd 开关:纯推理场景下,用 with torch.no_grad(): 包裹,避免构建计算图——这对 SVD/QR 等无参数操作影响显著
最常被忽略的是:torch.linalg 函数默认不支持 torch.bfloat16,即使模型用 bfloat16 训练,分解时也得临时转成 float32,这个转换本身可能成为瓶颈。


















