优化基于二维空间点的树状grid节点搜索方法
结构化网格点定位:平方判断逻辑与性能优化
关于平方判断的原因
从代码逻辑来看,参数r实际代表的是径向距离的平方(比如极坐标下的r² = x² + y²),而xmin/xmax是径向方向的线性边界值。使用平方对比而非开方后对比,核心目的是避免耗时的开方浮点运算——开方操作的计算成本远高于乘法,直接用平方值做比较能显著减少单步判断的计算量,提升整体遍历效率。
如果你的场景中r是实际径向距离(而非平方值),当前的判断逻辑是错误的,需要改为cout['xmin'] <= np.sqrt(r) <= cout['xmax'],但现有代码的设计显然是让r传入平方值,以此换取性能。
性能优化建议
目前启用Numba-JIT后耗时14秒,但仍有较大优化空间,以下是针对性的优化点:
1. 预计算平方值,消除重复运算
当前函数中每次判断都要重复计算xmin²和xmax²,这是最大的性能损耗源之一。建议直接在grid结构化数组中新增xmin_sq和xmax_sq字段,一次性完成所有节点的平方计算并存储。定位函数中直接读取预计算的平方值,省去大量重复的乘法操作。
2. 优化数组访问模式
Numba对连续numpy数组的访问效率远高于结构化数组的字段访问:
- 将
grid的各个字段提取为独立的一维数组(比如grid_xmin_sq = grid['xmin_sq']、grid_ymin = grid['ymin']),在函数中直接使用这些数组进行索引判断。 - 提前提取当前节点的子节点ID列表(
child_ids = cout['children'][:cout['nChildren']]),避免在循环中重复执行切片和索引操作。
3. 精简循环与分支逻辑
- 将
NMAX设置为树的实际最大深度(而非1e6),避免不必要的循环范围检查。 - 把点在单元格内的判断逻辑封装为一个小的辅助函数,Numba会自动内联这类函数,减少代码冗余并提升执行效率。
- 尽量减少回溯逻辑:如果起始节点
c_index是包含目标点的节点,可以去掉回溯到父节点的分支,只保留向下遍历子节点的逻辑;若起始节点可能不包含点,建议直接从根节点开始遍历,避免回溯带来的分支开销。
4. 最大化Numba优化效果
使用@numba.njit(fastmath=True, cache=True)装饰函数,开启快速数学运算和缓存功能。如果能提前为grid指定明确的结构化类型(而非依赖自动推断),Numba的优化会更彻底。
原函数代码
def locate_photon_cell_mirror(r, z, c_index, grid): NMAX = 1000000 found = False cout_index = c_index abs_z = np.abs(z) for j in range(NMAX): cout = grid[cout_index] if (cout['xmin']**2 <= r and cout['xmax']**2 >= r and cout['ymin'] <= abs_z and cout['ymax'] >= abs_z): if (cout['nChildren'] == 0): found = True return cout_index, found flag = True for i in range(cout['nChildren']): child_cell = grid[cout['children'][i]] if (child_cell['xmin']**2 <= r and child_cell['xmax']**2 >= r and child_cell['ymin'] <= abs_z and child_cell['ymax'] >= abs_z): cout_index = cout['children'][i] flag = False break if (flag): cout_index = -999999 return cout_index, found else: cout_parent = cout['parent'] if cout_parent != -1: cout_index = cout_parent else: cout_index = -999999 return cout_index, found cout_index = -999999 return cout_index, found
内容的提问来源于stack exchange,提问作者matts
相关产品推荐
相关产品推荐

