Files
2026-07-04 02:40:45 +08:00

85 lines
3.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.
# EfficientWordCloud 并行优化设计文稿
## 1. 目标与背景
本设计针对 EfficientWordCloud 的两个性能瓶颈进行优化:
- **Python 侧**:文本渲染与 bbox 计算属于 CPU 密集型,原流程在主循环中串行执行。
- **C++ 侧**:可用位置搜索为线性扫描,且非线程安全,限制多核利用。
目标:
- 在 Python 侧引入并行 bbox 预取,降低主循环阻塞。
- 在 C++ 侧实现线程安全与分块并行搜索,提升多核性能。
## 2. 总体架构
### 2.1 并行策略
- **Python 侧**Producer-Consumer 预取模式。
- 使用 `ProcessPoolExecutor` 异步计算未来词语的 bbox。
- 主循环消费预取结果;若字体缩小,则回退为同步计算。
- **C++ 侧**Chunked Parallel Search。
- 将候选坐标分块,每块由一个异步任务扫描。
- 收集所有任务结果,选择最小索引对应的位置,以保持“中心优先”的排序策略。
### 2.2 线程安全模型
- `IntegralGrid` 内部引入 `std::shared_mutex`
- **读**`get_area_sum`)在并行搜索期间不再加锁,假设搜索阶段只读且在生成坐标与积分图后保持快照。
- **写**`update_rect_add`)当前实现默认由单线程 Python 调用,移除了锁以减少开销;如需多线程更新需恢复写锁保护。
- 重建积分图(`rebuild_integral`)只在写路径触发。
## 3. C++ 核心设计
### 3.1 数据结构扩展
-`IntegralGrid` 内部新增:
```cpp
mutable std::shared_mutex mutex_;
```
### 3.2 并行搜索流程
1. 计算线程数(`hardware_concurrency`),确定分块大小。
2. 对 `valid_coords` 分块后并行扫描,每块返回一个 `SearchResult`。
3. 主线程汇总所有结果,选取最小索引(全局最佳位置)。
4. 在搜索期间释放 GIL
```cpp
Py_BEGIN_ALLOW_THREADS
...
Py_END_ALLOW_THREADS
```
### 3.3 关键函数
- `search_range(start, end, box_h, box_w, step)`:扫描单块坐标。
- `find_spot_parallel(box_h, box_w, step)`:组织并行任务并聚合结果。
- `Grid_query_sorted`:绑定层调用 `find_spot_parallel`。
## 4. Python 侧设计
### 4.1 可序列化的测量函数
模块级函数保证可被 `ProcessPoolExecutor` 调度:
```python
def measure_text(text, font_path, size, rotate) -> (int, int)
```
### 4.2 ParallelBBoxFetcher
职责:
- 维护任务队列。
- 提交预取任务。
- 主循环中拉取结果(若无缓存则同步测量)。
接口:
- `prefetch(items)`
- `get(key, text, size, rotate)`
### 4.3 主流程集成
- 预先生成 `rotation_flags`,确保预取与实际一致。
- 预取前 `N` 个词的 bbox。
- 逐词处理时,提前预取下一批的 bbox。
- 字体缩小后回退同步,保证正确性。
## 5. 构建配置
- 编译标准升级为 C++17 以使用 `std::shared_mutex`。
## 6. 影响与兼容性
- 对外 API 保持不变。
- 性能提升取决于多核环境及词数量。
- 并行搜索仍保证排序一致性。
## 7. 风险与对策
- **多进程 bbox 测量开销**:采用预取窗口控制并发规模。
- **锁开销**:只在必要时加锁,读操作使用共享锁。
- **一致性**:聚合结果按最小索引保证行为与原排序一致。