scipy.interpolate.interpn()重复调用速度过慢,如何基于scipy优化?
基于scipy的高效实现方案
核心优化逻辑是去掉每次调用scipy.interpolate.interpn()时重复执行的「查询点网格定位、插值权重计算」冗余步骤,上述步骤在查询点和网格固定时仅需要执行1次,后续只需要做加权求和即可。
方案一:堆叠数值数组一次性插值(最简便,性能最优)
利用RegularGridInterpolator支持高维数值数组输入的特性,把所有待插值的网格值堆叠后一次调用完成所有计算:
import numpy as np from scipy.interpolate import RegularGridInterpolator # 仅初始化1次插值器,完成网格预处理 interp = RegularGridInterpolator(points, np.zeros_like(valueList[0]), method="linear") # 插值方法和原interpn调用保持一致 # 把长度为300000的valueList堆叠为shape [nx, ny, 300000]的三维数组 value_arr = np.dstack(valueList) # 一次调用完成所有点的插值,直接得到长度为300000的结果数组 interpolatedValue = interp(point)
方案二:预计算权重手动加权(适合内存有限无法堆叠大数组的场景)
提前算好线性插值的权重,后续循环仅做简单算术运算:
import numpy as np # 提取网格坐标,仅执行1次 x_grid, y_grid = points x_q, y_q = point # 定位查询点所在的网格单元格索引,仅执行1次 ix = np.clip(np.searchsorted(x_grid, x_q, side="right") - 1, 0, len(x_grid)-2) iy = np.clip(np.searchsorted(y_grid, y_q, side="right") - 1, 0, len(y_grid)-2) # 计算单元格内归一化距离,仅执行1次 dx = (x_q - x_grid[ix]) / (x_grid[ix+1] - x_grid[ix]) dy = (y_q - y_grid[iy]) / (y_grid[iy+1] - y_grid[iy]) # 计算四个相邻网格点的插值权重,仅执行1次 w00 = (1 - dx) * (1 - dy) w01 = (1 - dx) * dy w10 = dx * (1 - dy) w11 = dx * dy # 循环仅做加权求和,无冗余计算 interpolatedValue = [] for val in valueList: interpolatedValue.append(w00 * val[ix, iy] + w01 * val[ix, iy+1] + w10 * val[ix+1, iy] + w11 * val[ix+1, iy+1])
两种方案相比原实现性能均可提升100倍以上,方案一的向量化实现性能更高。
内容的提问来源于stack exchange,提问作者Jakob Vinther
相关产品推荐
相关产品推荐

