Python代码优化:加速大型雅克比矩阵计算

本文分析如何优化一个计算雅克比矩阵的Python函数,尤其是在 self.nself.m 很大(例如300)时,如何提高其计算速度。

原始代码:pythondef _make_Jac(self): # 这里计算雅克比矩阵,直角坐标形式。 Jacol = np.zeros([2(self.n-1), 2(self.n-1)]) Jacoh = np.zeros([2(self.n-1), 2(self.n-1)]) for i in tqdm(range(self.n - 1)): time.sleep(1) for j in range(self.n -1): if i == j: #对角线上 #计算P相关 #(2i,2j) tt = -1 * (self.e[i] * self.G[i,j]+ self.f[i] * self.B[i,j]) Jacol[2i,2j] = tt.l Jacoh[2i,2j] = tt.h #(2i,2j+1) tt = self.e[i] * self.B[i,j] - self.f[i] * self.G[i,j] Jacol[2i,2j + 1] = tt.l Jacoh[2i,2j + 1] = tt.h #分情况计算Q相关及U2相关 if i > self.m: #此时考虑U #(2i+1,2j) Jacol[2i + 1,2j] = 0 Jacoh[2i + 1,2j] = 0 #(2i+1,2j+1) Jacol[2i + 1,2j + 1] = 0 Jacoh[2i + 1,2j + 1] = 0 else: #此时考虑Q #(2i+1,2j) tt = self.e[i] * self.B[i,j] - self.f[i] * self.G[i,j] Jacol[2i + 1,2j] = tt.l Jacoh[2i + 1,2j] = tt.h #(2i+1,2j+1) tt = self.e[i] * self.G[i,j] + self.f[i] * self.B[i,j] Jacol[2i + 1,2j + 1] = tt.l Jacoh[2i + 1,2j + 1] = tt.h else: #非对角线上 #计算P相关 #(2i,2j) tt = itv(0,0) for k in range(self.n): tt -= self.e[k] * self.G[i,k] - self.f[k] * self.B[i,k] tt -= self.e[i] * self.G[i,i] tt -= self.f[i] * self.B[i,i] Jacol[2i,2j] = tt.l Jacoh[2i,2j] = tt.h #(2i,2j+1) tt = itv(0,0) for k in range(self.n): tt -= self.f[k] * self.G[i,k] + self.e[k] * self.B[i,k] tt += self.e[i] * self.B[i,i] tt -= self.f[i] * self.G[i,i] Jacol[2i,2j + 1] = tt.l Jacoh[2i,2j + 1] = tt.h #分情况计算Q相关及U2相关 if i > self.m: #此时考虑U #(2i+1,2j) tt = self.e[i] * (-2) Jacol[2i + 1,2j] = tt.l Jacoh[2i + 1,2j] = tt.h #(2i+1,2j+1) tt= 0 tt = self.f[i] * (-2) Jacol[2i + 1,2j + 1] = tt.l Jacoh[2i + 1,2j + 1] = tt.h else: #此时考虑Q #(2i+1,2j) tt = itv(0,0) for k in range(self.n): tt += self.f[k] * self.G[i,k] + self.e[k] * self.B[i,k] tt += self.e[i] * self.B[i,i] tt -= self.f[i] * self.G[i,i] Jacol[2i + 1,2j] = tt.l Jacoh[2i + 1,2j] = tt.h #(2i+1,2j+1) tt = itv(0,0) for k in range(self.n): tt -= self.e[k] * self.G[i,k] - self.f[k] * self.B[i,k] tt += self.e[i] * self.G[i,i] tt += self.f[i] * self.B[i,i] Jacol[2i + 1,2j + 1] = tt.l Jacoh[2i + 1,2j + 1] = tt.h self.Jaco = itv(Jacol, Jacoh)

优化建议:

  1. 向量化计算: 使用NumPy的数组操作和广播机制替换循环,例如将 self.e[k] * self.G[i,k] 的循环计算转换为 self.e * self.G[i,:] 的向量乘法。2. 减少重复计算: * 将循环内部不变的计算结果保存到临时变量中,例如 self.e[i] * self.G[i,i]self.f[i] * self.B[i,i]。 * 预先计算 self.e * self.Gself.f * self.B 等矩阵乘积,避免在循环内部重复计算。3. 并行化计算: * 使用 multiprocessingjoblib 等库将计算任务分配到多个CPU核心上并行执行,特别是对于大型矩阵的计算。4. 更高效的数据结构: * 如果矩阵 JacolJacoh 存在大量零元素,可以考虑使用稀疏矩阵存储,例如 scipy.sparse 模块提供的稀疏矩阵格式。5. 编译器优化: * 使用 Numba 等即时编译器将Python代码转换为机器码,提高代码执行效率。 * 使用 Cython 将关键代码段转换为 C 扩展模块,进一步提升性能。

优化后的代码示例(部分向量化):pythondef _make_Jac(self): # 初始化雅克比矩阵 Jacol = np.zeros([2(self.n-1), 2(self.n-1)]) Jacoh = np.zeros([2(self.n-1), 2(self.n-1)])

# 预先计算重复使用的值    eG = self.e[:, np.newaxis] * self.G  # 使用广播机制    fB = self.f[:, np.newaxis] * self.B  

for i in tqdm(range(self.n - 1)):        for j in range(self.n - 1):            if i == j:                # 对角线元素计算                Jacol[2*i, 2*j] = (-eG[i, j] - fB[i, j]).l                Jacoh[2*i, 2*j] = (-eG[i, j] - fB[i, j]).h                # ... 其他对角线元素计算 ...            else:                # 非对角线元素计算                Jacol[2*i, 2*j] = (-np.sum(eG[i, :]) - np.sum(fB[i, :])).l                Jacoh[2*i, 2*j] = (-np.sum(eG[i, :]) - np.sum(fB[i, :])).h                # ... 其他非对角线元素计算 ...

self.Jaco = itv(Jacol, Jacoh)

总结:

通过上述优化方法,可以显著提高大型雅克比矩阵计算的效率。实际应用中,需要根据具体情况选择合适的优化策略。

Python代码优化:加速大型雅克比矩阵计算

原文地址: https://www.cveoy.top/t/topic/bRff 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录