Files
massive-cloud/docs/整车配准算法性能分析报告.md
lipan 29f1d45d66 feat: 算法升级、整车配准集成与性能分析文档
算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3
适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新
后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动
前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复
文档: 新增5份算法性能分析报告
2026-06-25 08:22:20 +00:00

161 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 整车配准算法性能分析报告
> 分析时间:2026-06-25
> 算法版本:`整车配准v1.3`
> 入口函数:`translate_align_by_front_tail`(`translate_align_pointcloud_to_cad.py`)
> 测试环境:INTEL SSDSC2KB01(SATA SSD,~394 MB/s);A100 40 GB;CPU 128 核
> **实测数据**:12 GB / 10 亿点 binary PLY 输入,总耗时 **10 min 24 s**
---
## 执行流程总览
```
translate_align_by_front_tail()
├─ 1. CAD STEP → mesh → 30k 点云采样 ← 实测 6 min 30 s(无 cache 时)
│ └─ [cache 命中] 直接加载 .ply ← 实测 ~5 s
├─ 2. 加载原始点云(Open3D binary PLY) ← 实测 1 min 17 s
├─ 3. 车头 / 车尾裁剪 × 4 ← 实测 2 min 17 s
├─ 4. 车头 / 车尾局部采样(1000 pts × 4)← 实测 7.6 ms
├─ 5. 平移估计(点集质心差) ← 实测 1.3 ms
├─ 6. ICP 精配准(采样 20 万点) ← 实测 1.9 s
├─ 7. 应用变换 + 写入配准结果 PLY ← 实测 12.8 s
└─ 8. 对齐误差统计(采样 10 万点 KNN) ← 实测 977 ms
```
---
## 各步骤详细说明与时间估算
### 第一阶段:CAD 准备(STEP → 采样点云)
| # | 步骤 | 代码位置 | 说明 | 无 cache | 有 cache |
|---|---|---|---|---|---|
| 1a | `read_step_file`(OCC 加载) | `translate_align...py:73` | OCC `STEPControl_Reader` 读 STEP | ~10 s | 跳过 |
| 1b | `BRepMesh_IncrementalMesh`(tessellate) | `translate_align...py:147` | OCC 三角剖分,147,275 个面 | **~6 min** | 跳过 |
| 1c | 提取顶点/三角形数组 | `translate_align...py:100` | Python for loop 遍历所有面 | ~15 s | 跳过 |
| 1d | `o3d.PointCloud` + 均匀采样 30k 点 | `translate_align...py:155` | 从 mesh 均匀采样 `cad_sample_points=30000` | ~3 s | 跳过 |
| 1e | **加载 cache PLY**(`useCadCache=true`) | `translate_align...py:510` | 直接读 1.4 MB PLY,30k 点 | — | **~1 s** |
> **CAD cache 机制**:首次运行时 STEP tessellate 需约 6 分钟,生成 `cad_cache/<hash>.ply`(1.4 MB)。后续所有运行直接加载 cache,耗时降至 1 秒以内。**务必开启 `useCadCache=true`(已默认开启)**,且不要删除 `cad_cache/` 目录。
---
### 第二阶段:加载原始点云
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 2 | `o3d.io.read_point_cloud`(binary PLY) | `translate_align...py:547` | Open3D C++ 读 12 GB binary PLY,直接构造 PointCloud | **~1 min 17 s** |
Open3D 读取速度约 158 MB/s(受限于磁盘顺序读速 ~394 MB/s + float 转换)。12 GB 需要约 75 秒,无法进一步优化除非换更快的磁盘。
---
### 第三阶段:车头 / 车尾裁剪(主要瓶颈)
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 3 | `crop_end_region_by_ratio` × 4 | `translate_align...py:180` | 对 10 亿点 Open3D PointCloud 做 4 次 `pcd.crop(AABB)`(CAD 前/后 + 扫描前/后) | **~2 min 17 s** |
虽然 `o3d.crop` 是 C++ 实现,但对 10 亿点的 PointCloud 内部仍需遍历全量点做 AABB 测试(O(N) × 4 次),实测每次约 34 秒,4 次共计 137 秒。
裁剪后车头/尾各只有 ~几千到几万点(ratio=0.01,即取前 1% 长度),所以裁剪结果本身非常小,耗时全部来自对全量 10 亿点的遍历。
---
### 第四阶段:局部采样 + 粗配准
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 4 | `sample_farthest_points_simple` × 4 | `translate_align...py:235` | 随机采样 1000 点;裁剪后点数已很少,O(M) | **7.6 ms** |
| 5 | 平移估计 | `translate_align...py:638` | 车头质心差 + 车尾质心差均值估计初始平移 | **1.3 ms** |
---
### 第五阶段:ICP 精配准
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 6 | `sample_farthest_points_simple`(20 万点采样) | `translate_align...py:355` | 从 10 亿点随机采样 `icp_sample_points=200000` | **< 1 s** |
| 7 | `o3d.registration.registration_icp` | `translate_align...py:375` | Point-to-point ICP,source 20 万点 → target CAD 30k 点,最多 50 次迭代;Open3D C++ | **1.9 s** |
ICP 本身非常快,因为:
- source 只用 20 万点(采样)
- target CAD 只有 30k 点
- Open3D ICP 是 C++ SIMD 实现
---
### 第六阶段:应用变换 + 写入结果
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 8 | `aligned_pcd.transform(T_final)` | `translate_align...py:704` | 对 10 亿点做 4×4 矩阵变换(Open3D C++,SIMD) | **~2 s** |
| 9 | `write_point_cloud_float32_xyz` | `translate_align...py:314` | 分块写 binary PLY,float32,12 GB → 分 1000 个 chunk 写 | **~10 s** |
| 10 | 误差统计(`compute_error_stats`) | `translate_align...py:740` | 采样 10 万点,KNN 建树 + 查询,scipy C++ | **977 ms** |
---
## 实测时间汇总
| 阶段 | 实测时间 | 占比 |
|---|---|---|
| CAD 采样(无 cache) | **6 min 30 s** | 63% |
| CAD 采样(有 cache) | **~1 s** | <1% |
| **加载原始点云(Open3D)** | **1 min 17 s** | 12% |
| **车头/尾裁剪 × 4(Open3D C++ crop)** | **2 min 17 s** | 22% |
| 局部采样 + 平移估计 | **<0.01 s** | <1% |
| ICP 精配准(20 万点) | **1.9 s** | <1% |
| 写 12 GB 结果 PLY | **12.8 s** | 2% |
| 误差统计 | **977 ms** | <1% |
| **总计(有 cache)** | **~10 min 24 s** | — |
| **总计(无 cache,首次)** | **~17 min** | — |
---
## 主要瓶颈分析
### 瓶颈 1:车头/尾裁剪 2 min 17 s(无法简单绕过)
`pcd.crop(AABB)` 是 Open3D C++ 全量遍历,10 亿点 × 4 次不可避免。
```
缓解方案:将 crop_ratio 从 0.01 增大到 0.02–0.05,
提取更多点用于粗配准,同时不影响裁剪本身速度(依然 O(N))。
根本方案:将 Open3D PointCloud 替换为 numpy 数组,
4 次 crop 变为 4 次 numpy 布尔索引,
并行化(4 个 crop 独立,可多线程),
估计可从 2 min 17 s 降至 ~30 s。
```
### 瓶颈 2:加载原始点云 1 min 17 s(I/O 受限)
Open3D 读 12 GB 文件,受限于 SATA SSD 394 MB/s 顺序读速,理论下限约 30 s(NVMe),实测 77 s 说明还有额外开销(float 类型转换)。升级到 NVMe 可降至 ~35 s。
### 瓶颈 3:CAD tessellate 6 min(首次,已有 cache 机制解决)
OCC 对 147,275 个面的 CAD 做三角剖分只需要跑一次,结果缓存为 1.4 MB PLY。**只要 `useCadCache=true` 且 CAD 文件未更换,后续每次配准这一步只需 1 秒**。
---
## 优化目标
| 场景 | 当前 | 优化后目标 |
|---|---|---|
| 有 cache,12 GB 输入 | 10 min 24 s | ~4 min(crop 多线程 + numpy 化) |
| 首次运行(无 cache) | ~17 min | ~4 min + 6 min(CAD build 无法优化) |
---
## GPU 使用情况
| 模块 | GPU 使用 |
|---|---|
| STEP 解析 / tessellate(OCC) | ❌ CPU |
| 点云读取(Open3D) | ❌ CPU(I/O 受限) |
| crop / transform(Open3D) | ❌ CPU(C++ SIMD) |
| **ICP 精配准(Open3D)** | ❌ CPU(Open3D ICP 不使用 CUDA) |
| 误差统计(scipy KNN) | ❌ CPU |
**整车配准全程不使用 GPU**,A100 完全闲置。ICP 最有潜力用 GPU 加速(Open3D 有 `registration_colored_icp` + CUDA),但当前输入只有 20 万点,ICP 本身已是 1.9 s,瓶颈在 I/O 和 crop,GPU 化 ICP 收益有限。