Skip to content

Commit 696fa9f

Browse files
committed
docs: exo 源码架构分析 + Phase 1 集成策略
关键发现: - exo Apache 2.0 许可证,商业友好 - 核心分片算法 allocate_layers_proportionally ~200行,值得借鉴 - 三种分片: Pipeline/Tensor/CFG(MoE) - Rust 网络层太重,Hippo 不需要 - 集成策略: 借鉴算法 + 可选进程级集成(不 import)
1 parent a4aea53 commit 696fa9f

1 file changed

Lines changed: 130 additions & 0 deletions

File tree

docs/EXO_ANALYSIS.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# exo 源码架构分析 — Hippo 集成参考
2+
3+
**分析日期**: 2026-04-19
4+
**版本**: exo v0.3.69
5+
**License**: Apache 2.0 ✅
6+
**语言**: Python + Rust(网络层)
7+
8+
---
9+
10+
## 核心架构
11+
12+
```
13+
exo master (协调器)
14+
├── placement.py — 分片调度策略
15+
├── placement_utils.py — 按内存比例分配层
16+
└── topology.py — 网络拓扑管理
17+
18+
exo worker (工作节点)
19+
├── runner/llm_inference/ — 推理执行
20+
│ ├── runner.py — Runner 生命周期
21+
│ └── batch_generator.py — 批量生成
22+
├── engines/mlx/ — MLX 引擎
23+
│ ├── auto_parallel.py — 自动并行
24+
│ ├── cache.py — KV cache
25+
│ └── generator/ — 生成器
26+
└── plan.py — 执行计划
27+
28+
exo routing (通信)
29+
├── router.py — 消息路由
30+
├── event_router.py — 事件分发
31+
└── topics.py — 发布/订阅
32+
33+
exo api (对外接口)
34+
├── adapters/chat_completions.py — OpenAI 兼容
35+
├── adapters/ollama.py — Ollama 兼容
36+
└── adapters/claude.py — Claude API 兼容
37+
38+
rust/networking (底层通信)
39+
├── discovery.rs — mDNS/swarm 发现
40+
└── swarm.rs — P2P 通信
41+
```
42+
43+
## 分片策略(placement_utils.py)
44+
45+
**核心函数**: `allocate_layers_proportionally()`
46+
47+
```python
48+
# 按可用内存比例分配模型层
49+
def allocate_layers_proportionally(
50+
total_layers: int,
51+
memory_fractions: list[float], # 每台机器的内存占比
52+
) -> list[int]: # 每台机器分配的层数
53+
```
54+
55+
**示例**(双 M4 16GB 跑 Qwen3-35B 48层):
56+
- M4 #1: 13GB / 26GB = 50% → 24 层
57+
- M4 #2: 13GB / 26GB = 50% → 24 层
58+
59+
**分片类型**:
60+
- `PipelineShardMetadata` — Pipeline 并行(逐层传递 hidden state)
61+
- `TensorShardMetadata` — Tensor 并行(层内切分矩阵)
62+
- `CfgShardMetadata` — 条件推理(MoE 专家分发)
63+
64+
## 关键设计决策
65+
66+
### 1. Pipeline Parallelism(默认)
67+
- 每个 Worker 负责连续的层
68+
- Hidden state 通过网络传递到下一个 Worker
69+
- 简单、延迟可预测、适合家庭网络
70+
71+
### 2. Ring 通信(MLX)
72+
- `MlxRingInstance` — MLX ring backend 分布式
73+
- 利用 `mx.distributed` 的 send/recv
74+
- 需要 `MLX_RANK` + `MLX_HOSTFILE`
75+
76+
### 3. JAGGR 通信(自定义)
77+
- `MlxJacclInstance` — exo 自定义的集合通信
78+
- 比 ring 更灵活,支持 RDMA
79+
- Rust 实现,性能更好
80+
81+
### 4. 设备发现
82+
- mDNS(和 Hippo 一样)
83+
- + Bootstrap peers(手动指定)
84+
- + Swarm 协议(P2P 扩散)
85+
86+
## Hippo 可借鉴的部分
87+
88+
| 组件 | exo 实现 | Hippo 应该 |
89+
|------|---------|-----------|
90+
| 分片策略 | `allocate_layers_proportionally` | 直接借鉴,简单有效 |
91+
| Pipeline 调度 | Runner + Event 系统 | 简化版,用 asyncio |
92+
| 设备发现 | mDNS + Rust swarm | 已有(Phase 0) |
93+
| MLX 分布式 | ring/jaccl | 借鉴 ring 接口 |
94+
| API 兼容 | OpenAI/Ollama/Claude | 已有(Phase 0) |
95+
96+
## Hippo 不应该依赖的部分
97+
98+
| 组件 | 原因 |
99+
|------|------|
100+
| exo 的 Rust 网络层 | 太重,Hippo 用 Python aiohttp 足够 |
101+
| exo 的完整 API 层 | Hippo 已有自己的 |
102+
| exo 的 election 机制 | 家庭场景不需要选主 |
103+
| exo 的 image pipeline | Hippo 专注 LLM |
104+
105+
## 集成策略
106+
107+
**不 import exo**,而是借鉴核心算法 + 可选进程级集成:
108+
109+
```python
110+
# 借鉴算法(Hippo 自己实现)
111+
class PipelineScheduler:
112+
def allocate_layers(self, total_layers, workers):
113+
# 源自 exo 的 allocate_layers_proportionally
114+
memory_fractions = [w.memory / total for w in workers]
115+
return allocate_layers_proportionally(total_layers, memory_fractions)
116+
117+
# 可选集成(进程级,不 import)
118+
class ExoBackend(InferenceBackend):
119+
async def start(self):
120+
self._process = subprocess.Popen(["exo", ...])
121+
async def generate(self, prompt):
122+
# 通过 HTTP API 调用 exo
123+
async with aiohttp.ClientSession() as session:
124+
resp = await session.post("http://localhost:8000/v1/chat/completions", ...)
125+
```
126+
127+
---
128+
129+
**结论**: exo 的核心分片算法(~200行)值得直接借鉴。
130+
完整集成用进程级(subprocess + HTTP),不深度依赖。

0 commit comments

Comments
 (0)