iroh-tinker 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iroh_tinker-0.1.1/PKG-INFO +392 -0
- iroh_tinker-0.1.1/README.md +331 -0
- iroh_tinker-0.1.1/pyproject.toml +92 -0
- iroh_tinker-0.1.1/python/iroh_tinker/__init__.py +91 -0
- iroh_tinker-0.1.1/python/iroh_tinker/__main__.py +9 -0
- iroh_tinker-0.1.1/python/iroh_tinker/_native.py +162 -0
- iroh_tinker-0.1.1/python/iroh_tinker/_yaml.py +92 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/__init__.py +89 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/base.py +109 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/colossal_backend.py +180 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/jax_backend.py +237 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/mlx_backend.py +180 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/numpy_backend.py +160 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/pytorch_backend.py +275 -0
- iroh_tinker-0.1.1/python/iroh_tinker/backends/taichi_backend.py +389 -0
- iroh_tinker-0.1.1/python/iroh_tinker/checkpoint.py +108 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cli.py +559 -0
- iroh_tinker-0.1.1/python/iroh_tinker/client.py +269 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/__init__.py +25 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/__init__.py +20 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/aws.py +187 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/azure.py +140 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/base.py +154 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/cloudcli.py +111 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/gcp.py +134 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/local.py +138 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/ssh.py +145 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/job.py +242 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/rendezvous.py +233 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/runner.py +145 -0
- iroh_tinker-0.1.1/python/iroh_tinker/cloud/spec.py +268 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/__init__.py +80 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/allreduce.py +286 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/compression.py +240 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/gossip.py +68 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/nccl.py +126 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/rdma.py +237 -0
- iroh_tinker-0.1.1/python/iroh_tinker/comm/transport.py +564 -0
- iroh_tinker-0.1.1/python/iroh_tinker/compat/__init__.py +6 -0
- iroh_tinker-0.1.1/python/iroh_tinker/compat/sky_cli.py +193 -0
- iroh_tinker-0.1.1/python/iroh_tinker/compat/sky_yaml.py +86 -0
- iroh_tinker-0.1.1/python/iroh_tinker/device.py +126 -0
- iroh_tinker-0.1.1/python/iroh_tinker/fault_tolerance.py +121 -0
- iroh_tinker-0.1.1/python/iroh_tinker/hw.py +42 -0
- iroh_tinker-0.1.1/python/iroh_tinker/metrics.py +214 -0
- iroh_tinker-0.1.1/python/iroh_tinker/ofo.py +200 -0
- iroh_tinker-0.1.1/python/iroh_tinker/py.typed +0 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/__init__.py +23 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/engine.py +202 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/llm.py +155 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/model.py +133 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/sampling.py +51 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/schemas.py +147 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/server.py +266 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/tokenizer.py +26 -0
- iroh_tinker-0.1.1/python/iroh_tinker/serving/tp.py +136 -0
- iroh_tinker-0.1.1/python/iroh_tinker/shims.py +58 -0
- iroh_tinker-0.1.1/python/iroh_tinker/topology.py +107 -0
- iroh_tinker-0.1.1/python/iroh_tinker/types.py +173 -0
- iroh_tinker-0.1.1/python/iroh_tinker.egg-info/PKG-INFO +392 -0
- iroh_tinker-0.1.1/python/iroh_tinker.egg-info/SOURCES.txt +95 -0
- iroh_tinker-0.1.1/python/iroh_tinker.egg-info/dependency_links.txt +1 -0
- iroh_tinker-0.1.1/python/iroh_tinker.egg-info/entry_points.txt +2 -0
- iroh_tinker-0.1.1/python/iroh_tinker.egg-info/requires.txt +52 -0
- iroh_tinker-0.1.1/python/iroh_tinker.egg-info/top_level.txt +1 -0
- iroh_tinker-0.1.1/setup.cfg +4 -0
- iroh_tinker-0.1.1/tests/test_accel.py +124 -0
- iroh_tinker-0.1.1/tests/test_allreduce.py +158 -0
- iroh_tinker-0.1.1/tests/test_backends.py +92 -0
- iroh_tinker-0.1.1/tests/test_benchmarks.py +47 -0
- iroh_tinker-0.1.1/tests/test_client_iroh.py +82 -0
- iroh_tinker-0.1.1/tests/test_cloud_engines.py +149 -0
- iroh_tinker-0.1.1/tests/test_cloud_fake_cli.py +287 -0
- iroh_tinker-0.1.1/tests/test_cloud_job.py +190 -0
- iroh_tinker-0.1.1/tests/test_cloud_rendezvous.py +115 -0
- iroh_tinker-0.1.1/tests/test_cloud_runner.py +84 -0
- iroh_tinker-0.1.1/tests/test_cloud_spec.py +151 -0
- iroh_tinker-0.1.1/tests/test_colossal_backend.py +92 -0
- iroh_tinker-0.1.1/tests/test_compressed_transport.py +87 -0
- iroh_tinker-0.1.1/tests/test_device.py +31 -0
- iroh_tinker-0.1.1/tests/test_examples_smoke.py +85 -0
- iroh_tinker-0.1.1/tests/test_fault_tolerance.py +148 -0
- iroh_tinker-0.1.1/tests/test_hardware.py +29 -0
- iroh_tinker-0.1.1/tests/test_hw.py +24 -0
- iroh_tinker-0.1.1/tests/test_iroh_transport.py +143 -0
- iroh_tinker-0.1.1/tests/test_metrics_subnet_rdma.py +185 -0
- iroh_tinker-0.1.1/tests/test_nccl.py +79 -0
- iroh_tinker-0.1.1/tests/test_ofo.py +20 -0
- iroh_tinker-0.1.1/tests/test_serving.py +221 -0
- iroh_tinker-0.1.1/tests/test_shims.py +49 -0
- iroh_tinker-0.1.1/tests/test_sky_compat.py +168 -0
- iroh_tinker-0.1.1/tests/test_topology.py +36 -0
- iroh_tinker-0.1.1/tests/test_tp.py +89 -0
- iroh_tinker-0.1.1/tests/test_tp_transport.py +130 -0
- iroh_tinker-0.1.1/tests/test_training_loop.py +93 -0
- iroh_tinker-0.1.1/tests/test_types.py +40 -0
- iroh_tinker-0.1.1/tests/test_yaml_backend.py +76 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iroh-tinker
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Distributed training framework using iroh for 100k+ node scale across PyTorch, JAX, Taichi and more
|
|
5
|
+
Author: Research Team
|
|
6
|
+
License: MIT OR Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/scairesearch/iroh_tinker
|
|
8
|
+
Project-URL: Repository, https://github.com/scairesearch/iroh_tinker
|
|
9
|
+
Project-URL: Issues, https://github.com/scairesearch/iroh_tinker/issues
|
|
10
|
+
Keywords: distributed-training,iroh,p2p,allreduce,pytorch,jax,taichi,mlx
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: numpy>=1.24
|
|
24
|
+
Provides-Extra: torch
|
|
25
|
+
Requires-Dist: torch>=2.1; extra == "torch"
|
|
26
|
+
Provides-Extra: jax
|
|
27
|
+
Requires-Dist: jax>=0.4.20; extra == "jax"
|
|
28
|
+
Requires-Dist: jaxlib>=0.4.20; extra == "jax"
|
|
29
|
+
Provides-Extra: taichi
|
|
30
|
+
Requires-Dist: taichi>=1.6; extra == "taichi"
|
|
31
|
+
Provides-Extra: mlx
|
|
32
|
+
Requires-Dist: mlx>=0.5; extra == "mlx"
|
|
33
|
+
Provides-Extra: iroh
|
|
34
|
+
Requires-Dist: iroh>=0.1.0; extra == "iroh"
|
|
35
|
+
Provides-Extra: colossalai
|
|
36
|
+
Requires-Dist: colossalai>=0.4; extra == "colossalai"
|
|
37
|
+
Provides-Extra: cloud
|
|
38
|
+
Requires-Dist: pyyaml>=6.0; extra == "cloud"
|
|
39
|
+
Provides-Extra: aws
|
|
40
|
+
Requires-Dist: boto3>=1.34; extra == "aws"
|
|
41
|
+
Provides-Extra: gcs
|
|
42
|
+
Requires-Dist: google-cloud-storage>=2.10; extra == "gcs"
|
|
43
|
+
Provides-Extra: serve
|
|
44
|
+
Requires-Dist: fastapi>=0.110; extra == "serve"
|
|
45
|
+
Requires-Dist: uvicorn[standard]>=0.27; extra == "serve"
|
|
46
|
+
Requires-Dist: pydantic>=2.5; extra == "serve"
|
|
47
|
+
Requires-Dist: httpx>=0.27; extra == "serve"
|
|
48
|
+
Provides-Extra: sky
|
|
49
|
+
Requires-Dist: skypilot; extra == "sky"
|
|
50
|
+
Provides-Extra: spotty
|
|
51
|
+
Requires-Dist: spotty>=1.3; extra == "spotty"
|
|
52
|
+
Provides-Extra: dev
|
|
53
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
54
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
55
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
56
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
57
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
58
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
59
|
+
Provides-Extra: zamlpy
|
|
60
|
+
Requires-Dist: zamlpy>=0.2.0; extra == "zamlpy"
|
|
61
|
+
|
|
62
|
+
# iroh-tinker
|
|
63
|
+
|
|
64
|
+
Distributed training that scales from a laptop to **1,000,000 nodes** using
|
|
65
|
+
[iroh](https://www.iroh.computer/) for peer-to-peer QUIC gradient
|
|
66
|
+
synchronization — no cluster scheduler, no rendezvous server, no static IPs.
|
|
67
|
+
|
|
68
|
+
You write a normal training loop against a Tinker-style API; iroh-tinker
|
|
69
|
+
handles the distributed gradient allreduce, checkpoint sharding, fault
|
|
70
|
+
tolerance, and selects the right communication algorithm for your cluster size.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import iroh_tinker as it
|
|
74
|
+
|
|
75
|
+
client = it.TrainingClient(base_model="Qwen/Qwen3-8B", rank=0, world_size=8,
|
|
76
|
+
backend="pytorch", lora_rank=32)
|
|
77
|
+
|
|
78
|
+
for batch in dataloader:
|
|
79
|
+
client.forward_backward(batch, loss_fn="cross_entropy")
|
|
80
|
+
client.optim_step(it.AdamParams(learning_rate=1e-4))
|
|
81
|
+
if client.step % 100 == 0:
|
|
82
|
+
client.save_state()
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quickstart
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# install (from a checkout)
|
|
89
|
+
pip install -e .
|
|
90
|
+
|
|
91
|
+
# or with optional backends
|
|
92
|
+
pip install -e ".[torch,jax]"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import iroh_tinker as it
|
|
97
|
+
|
|
98
|
+
client = it.TrainingClient(base_model="tiny", backend="numpy", rank=0, world_size=1)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Use the CLI:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
iroh-tinker backends # list backends
|
|
105
|
+
iroh-tinker device # detect CUDA/ROCm/RISC-V/CPU
|
|
106
|
+
iroh-tinker topology 100000 # show fanout/levels for 100k nodes
|
|
107
|
+
iroh-tinker train --steps 20 # short local training loop
|
|
108
|
+
iroh-tinker bench --world-size 8 # allreduce micro-benchmarks
|
|
109
|
+
iroh-tinker --json device # machine-readable output
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Why
|
|
113
|
+
|
|
114
|
+
Existing distributed trainers (DDP, FSDP, ColossalAI) assume a tightly-coupled
|
|
115
|
+
data center: shared filesystem, NCCL, a rendezvous host. iroh-tinker instead
|
|
116
|
+
routes gradient exchange over iroh's QUIC connections, which hole-punch through
|
|
117
|
+
NATs and fall back to relays, so ranks can live in different clouds or regions.
|
|
118
|
+
The communication layer is *hierarchical*, so no node ever talks to more than a
|
|
119
|
+
bounded number of peers regardless of total cluster size.
|
|
120
|
+
|
|
121
|
+
## Features
|
|
122
|
+
|
|
123
|
+
- **Multi-framework.** First-class backends for PyTorch (LoRA on HuggingFace
|
|
124
|
+
models), JAX, Taichi (CPU/CUDA/Metal/Vulkan/OpenGL), MLX, and a pure-NumPy
|
|
125
|
+
fallback for CI and CPU-only nodes.
|
|
126
|
+
- **Real P2P transport.** `IrohTransport` runs gradient exchange over iroh QUIC:
|
|
127
|
+
ticket-based rendezvous, one connection per rank, and hub-relay so any-to-any
|
|
128
|
+
collectives work on a bounded-fan-out overlay. An in-process transport mirrors
|
|
129
|
+
it for tests and simulations.
|
|
130
|
+
- **Hierarchical allreduce.** Ring (< 100 ranks), Tree (100–10k), and Butterfly
|
|
131
|
+
(≥ 10k) with a hierarchical wrapper, selected automatically.
|
|
132
|
+
- **Tinker-compatible API.** `forward_backward`, `optim_step`, `sample`,
|
|
133
|
+
`save_state` / `load_state`, plus `ServiceClient` / `SamplingClient`.
|
|
134
|
+
- **Gradient compression.** 8-bit block quantization and top-k sparsification
|
|
135
|
+
with error feedback to cut bandwidth by up to 100×.
|
|
136
|
+
- **Sharded checkpointing.** Content-addressed shards (SHA-256) with a manifest,
|
|
137
|
+
so a recovering rank fetches only its own shard.
|
|
138
|
+
- **Rust core (optional).** A high-performance core for networking, allreduce,
|
|
139
|
+
and scheduling lives under `src/` and is exposed behind optional Cargo
|
|
140
|
+
features.
|
|
141
|
+
- **Multi-cloud launch.** A SkyPilot-compatible `task.yaml` and thin native
|
|
142
|
+
drivers for GCP/AWS/Azure/SSH, with spot failover and reading the same
|
|
143
|
+
rendezvous as training — no VPC peering required.
|
|
144
|
+
- **OpenAI-compatible serving.** A vLLM-style engine (continuous batching,
|
|
145
|
+
`/v1/chat/completions`, SSE streaming) with tensor parallelism over iroh.
|
|
146
|
+
|
|
147
|
+
## Install
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Python package (NumPy only, works everywhere)
|
|
151
|
+
pip install -e python
|
|
152
|
+
|
|
153
|
+
# with a specific framework backend
|
|
154
|
+
pip install -e "python[torch]"
|
|
155
|
+
pip install -e "python[jax]"
|
|
156
|
+
pip install -e "python[taichi]"
|
|
157
|
+
pip install -e "python[mlx]"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Quickstarts
|
|
161
|
+
|
|
162
|
+
### Single process, any backend
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
python examples/train_all_backends.py # runs every backend that's installed
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Simulated multi-rank cluster (in-process, no network)
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
python examples/train_local_cluster.py --world-size 8 --backend numpy
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
After synchronization every rank reports the **same parameter checksum** — proof
|
|
175
|
+
that the allreduce is exact.
|
|
176
|
+
|
|
177
|
+
### Real distributed run
|
|
178
|
+
|
|
179
|
+
Run one process per rank (each on its own machine or container). Ranks discover
|
|
180
|
+
each other over iroh and synchronize gradients peer-to-peer:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# on each node i of 8 (shared rendezvous dir, e.g. NFS or a KV store):
|
|
184
|
+
RANK=$i WORLD=8 USE_IROH=1 python examples/train_pytorch.py
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
To try the real iroh path in one process (requires `pip install iroh`):
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
python examples/train_iroh_cluster.py --world-size 4 --steps 10
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Topology scaling
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
python examples/scale_topology.py
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
nodes= 8 levels=1 fanout=8 max_children=0
|
|
201
|
+
nodes= 100 levels=4 fanout=100 max_children=99
|
|
202
|
+
nodes= 10,000 levels=4 fanout=1,000 max_children=1,000
|
|
203
|
+
nodes= 100,000 levels=4 fanout=1,000 max_children=1,000
|
|
204
|
+
nodes=1,000,000 levels=4 fanout=10,000 max_children=10,000
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Multi-cloud launch (SkyPilot-compatible)
|
|
208
|
+
|
|
209
|
+
Launch the same job across providers with a thin, native driver per cloud —
|
|
210
|
+
no VPC peering, no central scheduler. Tasks are described with a SkyPilot
|
|
211
|
+
`task.yaml` superset, so existing task files work unchanged:
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
name: train
|
|
215
|
+
resources:
|
|
216
|
+
ordered: # try in order, fail over automatically
|
|
217
|
+
- {infra: gcp, accelerators: A100:8, use_spot: true}
|
|
218
|
+
- {infra: aws, accelerators: p5.48xlarge, use_spot: true}
|
|
219
|
+
workdir: .
|
|
220
|
+
setup: pip install -e ".[torch]"
|
|
221
|
+
run: torchrun --nproc-per-node 8 train.py
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
iroh-tinker launch task.yaml # provisions, installs, runs, renders
|
|
226
|
+
iroh-tinker launch task.yaml --dry-run
|
|
227
|
+
iroh-tinker jobs # list your clusters
|
|
228
|
+
iroh-tinker logs train --rank 0
|
|
229
|
+
iroh-tinker stop train
|
|
230
|
+
|
|
231
|
+
iroh-tinker sky launch task.yaml -c my-cluster # SkyPilot CLI verbs
|
|
232
|
+
iroh-tinker sky status | down my-cluster | logs my-cluster
|
|
233
|
+
iroh-tinker check # which engines / CLIs are available
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Native engines wrap `gcloud` / `aws` / `az` (and SSH hosts); SkyPilot and Spotty
|
|
237
|
+
are optional fallback engines. Ranks rendezvous through a shared ticket store
|
|
238
|
+
(local dir, S3, or GCS) and then talk directly over iroh — the same code path
|
|
239
|
+
whether the nodes share a data center or not. Set
|
|
240
|
+
`IROH_TINKER_RENDEZVOUS_SECRET` on every rank to HMAC-sign tickets (wrong or
|
|
241
|
+
tampered tickets raise `PermissionError`). Down ranks are detected via pid
|
|
242
|
+
checks on `status` and surfaced in `last_error`. Install the optional
|
|
243
|
+
`sky`/`vllm` PATH shims with `iroh-tinker --install-shims`.
|
|
244
|
+
|
|
245
|
+
## Serving (OpenAI-compatible, vLLM-style)
|
|
246
|
+
|
|
247
|
+
An inference server with continuous batching and a vLLM-shaped offline API:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
iroh-tinker serve --model tiny --tensor-parallel-size 1 --port 8000
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
curl localhost:8000/v1/chat/completions -H 'content-type: application/json' \
|
|
255
|
+
-d '{"model":"tiny","messages":[{"role":"user","content":"hi"}],"max_tokens":16}'
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Works with `openai`, LangChain, and llama-index clients (`base_url=http://host:8000/v1`).
|
|
259
|
+
Streaming (`"stream": true`, SSE), `/v1/models`, and `/v1/completions` are
|
|
260
|
+
supported. Offline generation mirrors vLLM:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from iroh_tinker.serving import LLM, SamplingParams
|
|
264
|
+
|
|
265
|
+
llm = LLM("tiny", tensor_parallel_size=1)
|
|
266
|
+
out = llm.generate(["hello"], SamplingParams(max_tokens=16, temperature=0.7))
|
|
267
|
+
print(out[0].outputs[0].text)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Tensor parallelism shards the LM head across ranks and all-gathers logits over
|
|
271
|
+
iroh; `serving/tp.py` is validated for bit-equality against single-rank output.
|
|
272
|
+
|
|
273
|
+
## Architecture
|
|
274
|
+
|
|
275
|
+
See [`ARCHITECTURE.md`](ARCHITECTURE.md) for the full design. In brief:
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
┌─────────────────────────────────────────┐
|
|
279
|
+
│ TrainingClient │
|
|
280
|
+
│ forward_backward → optim_step → save │
|
|
281
|
+
└───────────────┬─────────────────────────┘
|
|
282
|
+
│
|
|
283
|
+
┌──────────────────────┼──────────────────────┐
|
|
284
|
+
▼ ▼ ▼
|
|
285
|
+
┌────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
286
|
+
│ Backends │ │ Allreduce │ │ Checkpointing│
|
|
287
|
+
│ torch/jax/ │ │ ring/tree/ │ │ sha-256 │
|
|
288
|
+
│ taichi/mlx │ │ butterfly │ │ shards │
|
|
289
|
+
└────────────┘ └──────┬───────┘ └──────────────┘
|
|
290
|
+
▼
|
|
291
|
+
┌──────────────────┐
|
|
292
|
+
│ Transport │
|
|
293
|
+
│ iroh QUIC │ local │
|
|
294
|
+
└──────────────────┘
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Backend support
|
|
298
|
+
|
|
299
|
+
| Backend | Models | Autodiff | Device |
|
|
300
|
+
|-----------|---------------------------------|----------------|----------------------|
|
|
301
|
+
| PyTorch | HuggingFace causal LMs + LoRA | `autograd` | CUDA / MPS / CPU |
|
|
302
|
+
| JAX | custom transformer (Flax-ready) | `jax.grad` | CPU / GPU / TPU |
|
|
303
|
+
| Taichi | tied-embedding MLP | hand-written | CPU/CUDA/Metal/Vulkan|
|
|
304
|
+
| MLX | tied-embedding MLP | `value_and_grad`| Apple silicon |
|
|
305
|
+
| NumPy | tied-embedding MLP | hand-written | CPU |
|
|
306
|
+
|
|
307
|
+
All backends implement the same `TrainingBackend` interface
|
|
308
|
+
(`python/iroh_tinker/backends/base.py`), so the distributed loop is identical
|
|
309
|
+
regardless of framework.
|
|
310
|
+
|
|
311
|
+
## Testing
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
# Python
|
|
315
|
+
PYTHONPATH=python pytest tests -q
|
|
316
|
+
|
|
317
|
+
# Rust core
|
|
318
|
+
cargo test
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The transport/allreduce suite runs the real `IrohTransport` code path against an
|
|
322
|
+
in-process fake of the `iroh` API (`tests/_fake_iroh.py`), so the relay protocol,
|
|
323
|
+
barrier, and end-to-end distributed training are covered without a network.
|
|
324
|
+
|
|
325
|
+
## Performance
|
|
326
|
+
|
|
327
|
+
At 100k+ nodes the allreduce is bandwidth-bound. `CompressedTransport` compresses
|
|
328
|
+
each gradient buffer on the wire using self-describing frames
|
|
329
|
+
(`python/iroh_tinker/comm/compression.py`):
|
|
330
|
+
|
|
331
|
+
| Scheme | Wire reduction (1M params, 1% keep) | Typical use |
|
|
332
|
+
|-----------|------------------------------------|--------------------------|
|
|
333
|
+
| `8bit` | ~3.8x | accuracy-sensitive |
|
|
334
|
+
| `topk` | ~50x | sparse gradients |
|
|
335
|
+
| `topk8bit`| ~80x | aggressive bandwidth cut |
|
|
336
|
+
|
|
337
|
+
On a simulated 1 Gbps / 10us-latency link (`benchmarks/bench_bandwidth.py`), ring
|
|
338
|
+
allreduce of a 1M-element gradient shows ~2.6x (`8bit`), ~6.5x (`topk`) and
|
|
339
|
+
~6.3x (`topk8bit`) wall-clock speedup vs. uncompressed fp32. Real RDMA/InfiniBand
|
|
340
|
+
links push this higher since compression CPU cost becomes negligible relative to
|
|
341
|
+
the bandwidth saved on multi-GB models.
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# compression ratio vs. precision
|
|
345
|
+
PYTHONPATH=python python benchmarks/bench_compression.py
|
|
346
|
+
|
|
347
|
+
# allreduce algorithm scaling (star/ring/tree/butterfly) with/without compression
|
|
348
|
+
PYTHONPATH=python python benchmarks/bench_allreduce.py
|
|
349
|
+
|
|
350
|
+
# bandwidth-limited end-to-end speedup
|
|
351
|
+
PYTHONPATH=python python benchmarks/bench_bandwidth.py
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Hardware & topology
|
|
355
|
+
|
|
356
|
+
`python/iroh_tinker/device.py` detects CUDA (NVIDIA), ROCm/HIP (AMD), RISC-V and
|
|
357
|
+
CPU devices. `python/iroh_tinker/hw.py` derives an interconnect hint (NVLink/PCIe
|
|
358
|
+
vs. Ethernet) and adjusts allreduce fanout/group-size parameters accordingly.
|
|
359
|
+
`TrainingConfig.device` auto-resolves to the best available device (or accepts an
|
|
360
|
+
explicit `cuda`/`rocm`/`cpu` string), and `TrainingClient.device` exposes it.
|
|
361
|
+
|
|
362
|
+
`python/iroh_tinker/comm/rdma.py` provides a pluggable verbs transport:
|
|
363
|
+
`PyverbsBinding` talks to real IB/RoCE hardware via `pyverbs` (open device, PD,
|
|
364
|
+
MR, CQ, QP), while `LoopbackVerbsBinding` covers in-process tests with the same
|
|
365
|
+
framing. `build_loopback_cluster(n)` creates `n` linked transports for CI.
|
|
366
|
+
|
|
367
|
+
`python/iroh_tinker/ofo.py` implements OFA-style elastic subnet sampling:
|
|
368
|
+
`SubnetSampler` draws width/depth/kernel/resolution multipliers per hardware
|
|
369
|
+
tier (CUDA/ROCm/CPU/RISC-V) and narrows them against latency/memory/throughput
|
|
370
|
+
targets, deterministically with a seed.
|
|
371
|
+
|
|
372
|
+
## Observability
|
|
373
|
+
|
|
374
|
+
`iroh_tinker.metrics` is a dependency-free metrics registry (counters, gauges,
|
|
375
|
+
histograms) with Prometheus text exposition. `TrainingClient` records allreduce
|
|
376
|
+
latency, gradient bytes (raw vs. on-the-wire), compression ratio, and step
|
|
377
|
+
counts automatically. The serving stack exposes `GET /metrics` with
|
|
378
|
+
request/token/time-to-first-token series, and `iroh-tinker metrics` dumps the
|
|
379
|
+
in-process registry (`--snapshot` for JSON).
|
|
380
|
+
|
|
381
|
+
## API stability & deprecation
|
|
382
|
+
|
|
383
|
+
The v1 public surface is: `TrainingClient`, `TrainingConfig`, `Transport`,
|
|
384
|
+
`AllreduceAlgorithm`, and `TrainingBackend`. These follow semver: breaking
|
|
385
|
+
changes only in major releases. Experimental surfaces (`VerbsRdmaTransport`
|
|
386
|
+
hardware path, `ofo` hooks, `compat.sky_cli`) may change in minor releases and
|
|
387
|
+
will emit `FutureWarning` at least one minor release before removal. Internal
|
|
388
|
+
modules (`_*`) are not covered by the stability guarantee.
|
|
389
|
+
|
|
390
|
+
## License
|
|
391
|
+
|
|
392
|
+
MIT OR Apache-2.0
|