Initial project baseline

This commit is contained in:
2026-07-04 02:40:45 +08:00
commit d5d8caef2f
86 changed files with 15590 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
# 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 测量开销**:采用预取窗口控制并发规模。
- **锁开销**:只在必要时加锁,读操作使用共享锁。
- **一致性**:聚合结果按最小索引保证行为与原排序一致。
+61
View File
@@ -0,0 +1,61 @@
# EfficientWordCloud 使用文档
## 1. 构建与安装
在项目根目录执行:
```bash
python setup.py build
python setup.py install
```
## 2. 基本使用示例
```python
from efficient_wordcloud.wordcloud import EfficientWordCloud
freq = {
"hello": 100,
"world": 80,
"efficient": 60,
"wordcloud": 40
}
wc = EfficientWordCloud(
width=800,
height=600,
font_path="/path/to/font.ttf",
max_words=200,
min_font_size=8,
prefer_horizontal=0.9
)
wc.generate(freq)
img = wc.to_image()
img.show()
```
## 3. 关键参数说明
- `width` / `height`:画布尺寸。
- `font_path`:字体路径。
- `max_words`:最大词数。
- `min_font_size`:最小字体。
- `prefer_horizontal`:水平排版概率。
- `use_spiral_search`:是否启用中心优先排序搜索。
## 4. 并行优化的使用说明
### 4.1 Python bbox 预取
- 自动启用,无需额外配置。
- 内部使用 `ProcessPoolExecutor`,将未来词语的 bbox 计算并行化。
- 运行 `generate` 时会输出预取/等待日志,便于观察并行效果。
### 4.2 C++ 并行搜索
-`use_spiral_search=True` 时启用。
- 在 C++ 内部自动进行分块并行搜索,并保持中心优先排序的结果一致性。
## 5. 常见问题
### 5.1 为什么字体缩小时没有并行?
缩小字体后 bbox 依赖当前失败状态,需要同步确认以确保正确性。
### 5.2 多进程是否会导致额外内存开销?
是的,但任务仅用于 bbox 预取,且窗口大小有限,避免过度占用。
### 5.3 若没有字体文件怎么办?
会回退到 PIL 默认字体,但测量与渲染效果可能不同。