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.
Files changed (97) hide show
  1. iroh_tinker-0.1.1/PKG-INFO +392 -0
  2. iroh_tinker-0.1.1/README.md +331 -0
  3. iroh_tinker-0.1.1/pyproject.toml +92 -0
  4. iroh_tinker-0.1.1/python/iroh_tinker/__init__.py +91 -0
  5. iroh_tinker-0.1.1/python/iroh_tinker/__main__.py +9 -0
  6. iroh_tinker-0.1.1/python/iroh_tinker/_native.py +162 -0
  7. iroh_tinker-0.1.1/python/iroh_tinker/_yaml.py +92 -0
  8. iroh_tinker-0.1.1/python/iroh_tinker/backends/__init__.py +89 -0
  9. iroh_tinker-0.1.1/python/iroh_tinker/backends/base.py +109 -0
  10. iroh_tinker-0.1.1/python/iroh_tinker/backends/colossal_backend.py +180 -0
  11. iroh_tinker-0.1.1/python/iroh_tinker/backends/jax_backend.py +237 -0
  12. iroh_tinker-0.1.1/python/iroh_tinker/backends/mlx_backend.py +180 -0
  13. iroh_tinker-0.1.1/python/iroh_tinker/backends/numpy_backend.py +160 -0
  14. iroh_tinker-0.1.1/python/iroh_tinker/backends/pytorch_backend.py +275 -0
  15. iroh_tinker-0.1.1/python/iroh_tinker/backends/taichi_backend.py +389 -0
  16. iroh_tinker-0.1.1/python/iroh_tinker/checkpoint.py +108 -0
  17. iroh_tinker-0.1.1/python/iroh_tinker/cli.py +559 -0
  18. iroh_tinker-0.1.1/python/iroh_tinker/client.py +269 -0
  19. iroh_tinker-0.1.1/python/iroh_tinker/cloud/__init__.py +25 -0
  20. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/__init__.py +20 -0
  21. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/aws.py +187 -0
  22. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/azure.py +140 -0
  23. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/base.py +154 -0
  24. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/cloudcli.py +111 -0
  25. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/gcp.py +134 -0
  26. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/local.py +138 -0
  27. iroh_tinker-0.1.1/python/iroh_tinker/cloud/engines/ssh.py +145 -0
  28. iroh_tinker-0.1.1/python/iroh_tinker/cloud/job.py +242 -0
  29. iroh_tinker-0.1.1/python/iroh_tinker/cloud/rendezvous.py +233 -0
  30. iroh_tinker-0.1.1/python/iroh_tinker/cloud/runner.py +145 -0
  31. iroh_tinker-0.1.1/python/iroh_tinker/cloud/spec.py +268 -0
  32. iroh_tinker-0.1.1/python/iroh_tinker/comm/__init__.py +80 -0
  33. iroh_tinker-0.1.1/python/iroh_tinker/comm/allreduce.py +286 -0
  34. iroh_tinker-0.1.1/python/iroh_tinker/comm/compression.py +240 -0
  35. iroh_tinker-0.1.1/python/iroh_tinker/comm/gossip.py +68 -0
  36. iroh_tinker-0.1.1/python/iroh_tinker/comm/nccl.py +126 -0
  37. iroh_tinker-0.1.1/python/iroh_tinker/comm/rdma.py +237 -0
  38. iroh_tinker-0.1.1/python/iroh_tinker/comm/transport.py +564 -0
  39. iroh_tinker-0.1.1/python/iroh_tinker/compat/__init__.py +6 -0
  40. iroh_tinker-0.1.1/python/iroh_tinker/compat/sky_cli.py +193 -0
  41. iroh_tinker-0.1.1/python/iroh_tinker/compat/sky_yaml.py +86 -0
  42. iroh_tinker-0.1.1/python/iroh_tinker/device.py +126 -0
  43. iroh_tinker-0.1.1/python/iroh_tinker/fault_tolerance.py +121 -0
  44. iroh_tinker-0.1.1/python/iroh_tinker/hw.py +42 -0
  45. iroh_tinker-0.1.1/python/iroh_tinker/metrics.py +214 -0
  46. iroh_tinker-0.1.1/python/iroh_tinker/ofo.py +200 -0
  47. iroh_tinker-0.1.1/python/iroh_tinker/py.typed +0 -0
  48. iroh_tinker-0.1.1/python/iroh_tinker/serving/__init__.py +23 -0
  49. iroh_tinker-0.1.1/python/iroh_tinker/serving/engine.py +202 -0
  50. iroh_tinker-0.1.1/python/iroh_tinker/serving/llm.py +155 -0
  51. iroh_tinker-0.1.1/python/iroh_tinker/serving/model.py +133 -0
  52. iroh_tinker-0.1.1/python/iroh_tinker/serving/sampling.py +51 -0
  53. iroh_tinker-0.1.1/python/iroh_tinker/serving/schemas.py +147 -0
  54. iroh_tinker-0.1.1/python/iroh_tinker/serving/server.py +266 -0
  55. iroh_tinker-0.1.1/python/iroh_tinker/serving/tokenizer.py +26 -0
  56. iroh_tinker-0.1.1/python/iroh_tinker/serving/tp.py +136 -0
  57. iroh_tinker-0.1.1/python/iroh_tinker/shims.py +58 -0
  58. iroh_tinker-0.1.1/python/iroh_tinker/topology.py +107 -0
  59. iroh_tinker-0.1.1/python/iroh_tinker/types.py +173 -0
  60. iroh_tinker-0.1.1/python/iroh_tinker.egg-info/PKG-INFO +392 -0
  61. iroh_tinker-0.1.1/python/iroh_tinker.egg-info/SOURCES.txt +95 -0
  62. iroh_tinker-0.1.1/python/iroh_tinker.egg-info/dependency_links.txt +1 -0
  63. iroh_tinker-0.1.1/python/iroh_tinker.egg-info/entry_points.txt +2 -0
  64. iroh_tinker-0.1.1/python/iroh_tinker.egg-info/requires.txt +52 -0
  65. iroh_tinker-0.1.1/python/iroh_tinker.egg-info/top_level.txt +1 -0
  66. iroh_tinker-0.1.1/setup.cfg +4 -0
  67. iroh_tinker-0.1.1/tests/test_accel.py +124 -0
  68. iroh_tinker-0.1.1/tests/test_allreduce.py +158 -0
  69. iroh_tinker-0.1.1/tests/test_backends.py +92 -0
  70. iroh_tinker-0.1.1/tests/test_benchmarks.py +47 -0
  71. iroh_tinker-0.1.1/tests/test_client_iroh.py +82 -0
  72. iroh_tinker-0.1.1/tests/test_cloud_engines.py +149 -0
  73. iroh_tinker-0.1.1/tests/test_cloud_fake_cli.py +287 -0
  74. iroh_tinker-0.1.1/tests/test_cloud_job.py +190 -0
  75. iroh_tinker-0.1.1/tests/test_cloud_rendezvous.py +115 -0
  76. iroh_tinker-0.1.1/tests/test_cloud_runner.py +84 -0
  77. iroh_tinker-0.1.1/tests/test_cloud_spec.py +151 -0
  78. iroh_tinker-0.1.1/tests/test_colossal_backend.py +92 -0
  79. iroh_tinker-0.1.1/tests/test_compressed_transport.py +87 -0
  80. iroh_tinker-0.1.1/tests/test_device.py +31 -0
  81. iroh_tinker-0.1.1/tests/test_examples_smoke.py +85 -0
  82. iroh_tinker-0.1.1/tests/test_fault_tolerance.py +148 -0
  83. iroh_tinker-0.1.1/tests/test_hardware.py +29 -0
  84. iroh_tinker-0.1.1/tests/test_hw.py +24 -0
  85. iroh_tinker-0.1.1/tests/test_iroh_transport.py +143 -0
  86. iroh_tinker-0.1.1/tests/test_metrics_subnet_rdma.py +185 -0
  87. iroh_tinker-0.1.1/tests/test_nccl.py +79 -0
  88. iroh_tinker-0.1.1/tests/test_ofo.py +20 -0
  89. iroh_tinker-0.1.1/tests/test_serving.py +221 -0
  90. iroh_tinker-0.1.1/tests/test_shims.py +49 -0
  91. iroh_tinker-0.1.1/tests/test_sky_compat.py +168 -0
  92. iroh_tinker-0.1.1/tests/test_topology.py +36 -0
  93. iroh_tinker-0.1.1/tests/test_tp.py +89 -0
  94. iroh_tinker-0.1.1/tests/test_tp_transport.py +130 -0
  95. iroh_tinker-0.1.1/tests/test_training_loop.py +93 -0
  96. iroh_tinker-0.1.1/tests/test_types.py +40 -0
  97. 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