You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python多进程中传入半径列表批量计算激光雷达平面度

批量并行处理激光雷达平面度计算(优化多进程实现)

问题背景

现有激光雷达平面度计算函数,通过多进程对不同邻域半径值重复调用,但每次都要手动创建队列、进程变量,代码冗余且维护麻烦。希望能直接传入半径列表实现批量并行处理,简化流程。

优化方案

可以用multiprocessing.Pool替代手动管理进程和队列,它能自动处理任务分发、结果收集和进程生命周期管理,完美适配批量参数的并行计算需求。

步骤1:调整计算函数

去掉原函数中的output_queue参数,让函数直接返回计算结果,简化逻辑:

import numpy as np
from tqdm import tqdm

def calculate_planarity(lidar_data, neighborhood_radius, tree):
    planarity_values = np.zeros(len(lidar_data))
    try:
        for point_idx, point in tqdm(enumerate(lidar_data), total=len(lidar_data), desc=f"Radius={neighborhood_radius}"):
            neighbor_indices = tree.query_ball_point(point, neighborhood_radius)
            neighbors = lidar_data[neighbor_indices]

            if neighbors.shape[0] >= 3:
                cov_matrix = np.cov(neighbors, rowvar=False)
                eigenvalues, _ = np.linalg.eig(cov_matrix)
                sorted_eigenvalues = np.sort(eigenvalues)
                planarity = (sorted_eigenvalues[1] - sorted_eigenvalues[0]) / (sorted_eigenvalues.sum())
                planarity_values[point_idx] = planarity
            else:
                planarity_values[point_idx] = np.nan
    except Exception as e:
        print(f"Error in calculate_planarity (radius={neighborhood_radius}): {e}")
        raise
    return planarity_values

步骤2:用Pool实现批量并行处理

在主程序中,定义半径列表,通过Pool.starmap批量执行任务,自动收集结果:

from multiprocessing import Pool

if __name__ == "__main__":  
    # 假设inPoints和tree已经提前初始化
    radius_list = [1, 3, 10]
    
    # 创建进程池,进程数可根据CPU核心数调整,默认用全部核心
    with Pool() as pool:
        # 构建参数元组列表,每个元组对应一个任务的参数
        task_args = [(inPoints, radius, tree) for radius in radius_list]
        # 批量执行任务,获取结果列表
        planarity_results = pool.starmap(calculate_planarity, task_args)
    
    # 结果按半径顺序对应:planarity_results[0]是radius=1的结果,以此类推
    planarity_result = planarity_results[0]
    planarity_result3 = planarity_results[1]
    planarity_result10 = planarity_results[2]

进阶优化:减少大对象传递开销

如果lidar_data和tree是超大对象,每次传递会带来额外开销,可以用Pool的initializer参数把它们设为全局变量,避免重复序列化传递:

def init_worker(lidar_data_global, tree_global):
    global lidar_data, tree
    lidar_data = lidar_data_global
    tree = tree_global

def calculate_planarity_optimized(neighborhood_radius):
    # 直接使用全局变量lidar_data和tree,参数只保留radius
    planarity_values = np.zeros(len(lidar_data))
    try:
        for point_idx, point in tqdm(enumerate(lidar_data), total=len(lidar_data), desc=f"Radius={neighborhood_radius}"):
            neighbor_indices = tree.query_ball_point(point, neighborhood_radius)
            neighbors = lidar_data[neighbor_indices]

            if neighbors.shape[0] >= 3:
                cov_matrix = np.cov(neighbors, rowvar=False)
                eigenvalues, _ = np.linalg.eig(cov_matrix)
                sorted_eigenvalues = np.sort(eigenvalues)
                planarity = (sorted_eigenvalues[1] - sorted_eigenvalues[0]) / (sorted_eigenvalues.sum())
                planarity_values[point_idx] = planarity
            else:
                planarity_values[point_idx] = np.nan
    except Exception as e:
        print(f"Error in calculate_planarity (radius={neighborhood_radius}): {e}")
        raise
    return planarity_values

if __name__ == "__main__":  
    radius_list = [1, 3, 10]
    
    with Pool(initializer=init_worker, initargs=(inPoints, tree)) as pool:
        planarity_results = pool.map(calculate_planarity_optimized, radius_list)
    
    # 结果对应关系不变
    planarity_result, planarity_result3, planarity_result10 = planarity_results

优势说明

  • 无需手动创建队列和进程变量,代码简洁易维护
  • 自动处理进程的启动、执行、等待和结果收集
  • 支持批量传入任意长度的半径列表,扩展性强
  • 进阶优化方案减少大对象的重复传递,提升运行效率

内容的提问来源于stack exchange,提问作者Purple_Ad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:35:41