slice-packer-torus 1.1.0__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.
- slice_packer_torus-1.1.0/LICENSE +21 -0
- slice_packer_torus-1.1.0/PKG-INFO +216 -0
- slice_packer_torus-1.1.0/README.md +194 -0
- slice_packer_torus-1.1.0/pyproject.toml +47 -0
- slice_packer_torus-1.1.0/setup.cfg +4 -0
- slice_packer_torus-1.1.0/src/slice_packer_torus.egg-info/PKG-INFO +216 -0
- slice_packer_torus-1.1.0/src/slice_packer_torus.egg-info/SOURCES.txt +21 -0
- slice_packer_torus-1.1.0/src/slice_packer_torus.egg-info/dependency_links.txt +1 -0
- slice_packer_torus-1.1.0/src/slice_packer_torus.egg-info/entry_points.txt +2 -0
- slice_packer_torus-1.1.0/src/slice_packer_torus.egg-info/requires.txt +3 -0
- slice_packer_torus-1.1.0/src/slice_packer_torus.egg-info/top_level.txt +1 -0
- slice_packer_torus-1.1.0/src/slicepacker/__init__.py +110 -0
- slice_packer_torus-1.1.0/src/slicepacker/cli.py +438 -0
- slice_packer_torus-1.1.0/src/slicepacker/cordon.py +243 -0
- slice_packer_torus-1.1.0/src/slicepacker/embed.py +198 -0
- slice_packer_torus-1.1.0/src/slicepacker/hazard.py +319 -0
- slice_packer_torus-1.1.0/src/slicepacker/packing.py +382 -0
- slice_packer_torus-1.1.0/src/slicepacker/reconstitute.py +247 -0
- slice_packer_torus-1.1.0/src/slicepacker/tenant.py +267 -0
- slice_packer_torus-1.1.0/src/slicepacker/torus.py +269 -0
- slice_packer_torus-1.1.0/tests/test_hazard.py +180 -0
- slice_packer_torus-1.1.0/tests/test_mutations.py +463 -0
- slice_packer_torus-1.1.0/tests/test_slicepacker.py +507 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Margaret Nanyonga
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: slice-packer-torus
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: What a torus pod can actually still admit, what a chip failure costs, and who is allowed to fix it
|
|
5
|
+
Author: Margaret Nanyonga
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dimaggi-ai/slice-packer-torus
|
|
8
|
+
Project-URL: Research, https://dimaggi-ai.github.io/research
|
|
9
|
+
Keywords: torus,k-ary n-cube,capacity planning,fragmentation,multi-tenancy,fault domains
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Intended Audience :: System Administrators
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering
|
|
15
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest==8.3.4; extra == "dev"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# slice-packer-torus
|
|
24
|
+
|
|
25
|
+
**A pod's free-chip count is not its capacity, and a chip failure does not cost
|
|
26
|
+
one chip.**
|
|
27
|
+
|
|
28
|
+
A job on a torus-connected pod does not need chips. It needs a *rectangle* --- an
|
|
29
|
+
axis-aligned sub-grid, because that is the only shape whose diameter, bisection
|
|
30
|
+
and collective schedule anyone has computed. That one constraint turns four
|
|
31
|
+
ordinary operational questions into different questions than the ones capacity
|
|
32
|
+
reports answer:
|
|
33
|
+
|
|
34
|
+
| The question people ask | The question that decides the outcome |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| How many chips are free? | How large a job can still be placed? |
|
|
37
|
+
| What does a chip failure cost? | *Where* did the chip fail? |
|
|
38
|
+
| Can we recover automatically? | What does waiting for a human cost? |
|
|
39
|
+
| Can tenants be isolated? | Which requests make isolation impossible? |
|
|
40
|
+
|
|
41
|
+
Six geometric models, one measured failure history, a command line, and a
|
|
42
|
+
validation registry that prints what it declines to check before it prints
|
|
43
|
+
anything it does check.
|
|
44
|
+
|
|
45
|
+
**There is exactly one measurement in this repository** --- the Titan failure
|
|
46
|
+
history the hazard model reads. The geometry has no empirical anchor. See
|
|
47
|
+
[What this does not check](#what-this-does-not-check).
|
|
48
|
+
|
|
49
|
+
## Seven findings
|
|
50
|
+
|
|
51
|
+
**1. A pod described as a torus hands most jobs a mesh.** A slice inherits a
|
|
52
|
+
closed ring in a dimension only if it spans that dimension *completely*. Over
|
|
53
|
+
485 slices placed at random on a 16-ary 3-cube, not one received a
|
|
54
|
+
three-dimensional torus, and every slice lost at least one ring. The wraparound belongs to the pod; the job gets what is left.
|
|
55
|
+
|
|
56
|
+
**2. Free chips overstate capacity, and the gap widens as the pod fills.**
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
occupancy free placeable overstated trials with a gap
|
|
60
|
+
10% 3,217 2,953 8% 31/60
|
|
61
|
+
40% 2,131 1,696 20% 51/60
|
|
62
|
+
55% 1,547 1,090 30% 55/60
|
|
63
|
+
85% 634 448 29% 41/60
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**3. One chip failure costs between 6% and 50% of a slice, depending on where
|
|
67
|
+
it was.** Getting back to a rectangle means pulling a face in past the failure.
|
|
68
|
+
A corner costs one plane; the centre costs half the slice.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
where coordinate chips lost share
|
|
72
|
+
corner (0, 0, 0) 256 6.2%
|
|
73
|
+
face (0, 8, 8) 256 6.2%
|
|
74
|
+
interior (4, 8, 8) 1,280 31.2%
|
|
75
|
+
centre (8, 8, 8) 2,048 50.0%
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The worst case is **exactly half the slice for every shape**, so packing cannot
|
|
79
|
+
buy it down. The best case is `chips / longest axis` --- which means the compact
|
|
80
|
+
shape that wins on diameter is the one with the *highest* typical failure cost.
|
|
81
|
+
At 4,096 chips in a 64-ary pod, the compact `16x16x16` loses 256 chips to its
|
|
82
|
+
cheapest failure and the flat `1x64x64` loses 64.
|
|
83
|
+
|
|
84
|
+
**4. The option that keeps your checkpoint is the one that runs out first.**
|
|
85
|
+
Shrinking in place is cheap in hardware and breaks the rank grid, so the
|
|
86
|
+
checkpoint no longer restores. Moving at the same shape keeps the checkpoint and
|
|
87
|
+
costs other tenants their chips. Of 120 simulated failures a shrink existed in
|
|
88
|
+
all 120 and a same-shape move in only 97.
|
|
89
|
+
|
|
90
|
+
**5. Isolation has a price, and one request it cannot fill at any price.**
|
|
91
|
+
Dedicating a rack per tenant admitted 40,000 chips where an open pod took
|
|
92
|
+
75,392. And a job that wants a closed ring must span the axis, which means
|
|
93
|
+
touching every rack in it --- so "give me a torus" and "keep me off other
|
|
94
|
+
tenants' hardware" are contradictory, not merely competing.
|
|
95
|
+
|
|
96
|
+
**6. The approval queue becomes the outage exactly when the pod is busiest.**
|
|
97
|
+
Confining autonomous action to the failing job means anything that evicts a
|
|
98
|
+
neighbour needs a person. Share of failures that reach that boundary:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
occupancy 25%: 0/40 50%: 0/40 75%: 5/40 95%: 38/40
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`cost_of_waiting` prints what the L1 action gives up against the best action
|
|
105
|
+
available, and returns `None` --- never zero --- when there is no autonomous
|
|
106
|
+
action at all.
|
|
107
|
+
|
|
108
|
+
**7. On the one measured fleet, hazard-ranked *placement* pays and hazard-ranked
|
|
109
|
+
*eviction* does not.** New in 1.1: `hazard` reads the public Titan GPU lifetime
|
|
110
|
+
dataset --- 30,207 GPUs, 100,889 GPU-years (Ostrouchov et al., SC '20), fetched
|
|
111
|
+
and SHA-pinned by `make data`. Deaths per GPU-year climb 0.0009 → 0.0082 →
|
|
112
|
+
0.119 → 0.134 across the old batch's first four years (no infant mortality ---
|
|
113
|
+
the first year is the safest), and order 0.034 → 0.071 → 0.115 by cage, bottom
|
|
114
|
+
of the cooling path to top. Rank held-out chips by cohort hazard learned on the
|
|
115
|
+
other half of the fleet and the top 30% hold 55% of the deaths (lift 1.84×).
|
|
116
|
+
But price a preemptive drain against an unplanned reconstitution and even the
|
|
117
|
+
worst cohort rides unless the drain costs under ~3% of the rebuild: the
|
|
118
|
+
break-even hazard at a 90-day window and a 4:1 cost ratio is 1.17/GPU-year,
|
|
119
|
+
nearly nine times anything the fleet ever measured. Titan's operators reached the same
|
|
120
|
+
verdict in production: they re-cut the job mix onto reliable nodes; they did
|
|
121
|
+
not evict ahead of failure. The rates are Titan's own and do not transfer
|
|
122
|
+
(ASSUMPTIONS A12); the shape --- cohort beats fleet-uniform --- is the claim.
|
|
123
|
+
|
|
124
|
+
## Quickstart
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
make venv
|
|
128
|
+
make smoke-test # tests, registry and examples, under a minute
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
slicepacker example # the reference scenario end to end
|
|
133
|
+
slicepacker shapes 4096 -k 64 -n 3 # legal shapes, and which objective picks which
|
|
134
|
+
slicepacker cordon --shape 16,16,16 # what one chip costs, best to worst
|
|
135
|
+
slicepacker pack examples/pod-fragmented.json
|
|
136
|
+
slicepacker isolate examples/tenants-contradictory.json
|
|
137
|
+
slicepacker reconstitute examples/failure-no-room.json pretrain-7 4,8,8
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Exit codes are part of the interface: `0` answered, `1` **refused**, `2` the
|
|
141
|
+
input could not be read. A refusal is a correct answer, and a scheduler that
|
|
142
|
+
treats it as an error papers over the conditions this tool exists to surface.
|
|
143
|
+
|
|
144
|
+
## The models
|
|
145
|
+
|
|
146
|
+
| Module | What it decides |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| `torus` | k-ary n-cube diameter and bisection; whether a slice inherits a ring |
|
|
149
|
+
| `packing` | placement, fragmentation, the largest job still placeable |
|
|
150
|
+
| `cordon` | what it costs to get back to a rectangle after a chip dies |
|
|
151
|
+
| `embed` | shrink versus move, and the drain a move requires |
|
|
152
|
+
| `tenant` | blast-domain isolation, its price, and its contradictions |
|
|
153
|
+
| `reconstitute` | what a control plane may do alone, and what waiting costs |
|
|
154
|
+
| `hazard` | when a chip earns eviction before it fails, measured on the Titan fleet |
|
|
155
|
+
|
|
156
|
+
`docs/the-models.md` explains each in prose. `docs/integration.md` covers
|
|
157
|
+
wiring it to a scheduler.
|
|
158
|
+
|
|
159
|
+
## What this does not check
|
|
160
|
+
|
|
161
|
+
The validation registry prints sixteen declined items above its results on
|
|
162
|
+
every run. The first two matter most:
|
|
163
|
+
|
|
164
|
+
> No measured **packing**. Every geometry number here is a model output:
|
|
165
|
+
> nothing has been compared against a real torus pod or a real scheduler. The
|
|
166
|
+
> one measured thing is the **failure history** the hazard module reads, and
|
|
167
|
+
> it anchors failure rates only --- not one packing figure.
|
|
168
|
+
|
|
169
|
+
> The calibrated points pin textbook **closed forms**, which are identities
|
|
170
|
+
> about an idealised k-ary n-cube. Agreeing with them shows this code implements
|
|
171
|
+
> the model correctly. It is not evidence that the model describes any machine.
|
|
172
|
+
> The Titan points are the only cells anchored to a measured fleet --- and they
|
|
173
|
+
> anchor the *failure process*, not one packing figure.
|
|
174
|
+
|
|
175
|
+
Also declined: link failures, routing, time, correlated failure, non-rectangular
|
|
176
|
+
allocation, the reshard cost model, the L0/L1 boundary itself, first-fit
|
|
177
|
+
placement, what a rack is, the cost of refusing seam-straddling slices, the
|
|
178
|
+
paper's filtered device-level counts (the summary file cannot express them),
|
|
179
|
+
any transfer of Titan's rates to another machine, and repeated-play eviction.
|
|
180
|
+
|
|
181
|
+
The mutation tests in `tests/test_mutations.py` delete machinery on purpose and
|
|
182
|
+
assert the exact set of registry points that turns red. Nineteen mutations, a
|
|
183
|
+
green unmutated control so no red set can be an artefact, and two tests that
|
|
184
|
+
apply a real change and assert the registry does **not** notice --- because on
|
|
185
|
+
the geometry side it genuinely cannot. One Titan mutation earned its point a
|
|
186
|
+
sharper assertion: dropping the exposure clamp preserved every ordering and
|
|
187
|
+
first went red only once the mid-life magnitude was pinned. Every asserted red set was measured. Predicting them first was
|
|
188
|
+
wrong nine times out of seventeen, and two of those surprises were points that
|
|
189
|
+
had been passing on machinery that was no longer there.
|
|
190
|
+
|
|
191
|
+
## Reproducing
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
make data # fetch + SHA-verify the Titan dataset (once; ~4 MB)
|
|
195
|
+
make test # 104 unit tests and 22 mutation tests (~5 min: each mutation reruns the registry)
|
|
196
|
+
make validate # 29 registry points and 16 declined items
|
|
197
|
+
make examples # 24 examples, each pinned to its exit code
|
|
198
|
+
make experiments # the three figures quoted above; each exits 1 if it stops holding
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Reading order
|
|
202
|
+
|
|
203
|
+
- `DECISIONS.md` --- sixteen choices, what each bought and cost. Six were
|
|
204
|
+
forced by defects found while building this, and say so.
|
|
205
|
+
- `ASSUMPTIONS.md` --- twelve things taken as given.
|
|
206
|
+
- `SOURCES.md` --- three, and what they are and are not.
|
|
207
|
+
- `STATUS.md` --- what works, what is missing, what would change the answers.
|
|
208
|
+
|
|
209
|
+
## Series
|
|
210
|
+
|
|
211
|
+
Part of a program on the usable capacity of large accelerator fleets:
|
|
212
|
+
[dimaggi-ai.github.io/research](https://dimaggi-ai.github.io/research).
|
|
213
|
+
|
|
214
|
+
## Licence
|
|
215
|
+
|
|
216
|
+
MIT. Copyright (c) 2026 Margaret Nanyonga.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# slice-packer-torus
|
|
2
|
+
|
|
3
|
+
**A pod's free-chip count is not its capacity, and a chip failure does not cost
|
|
4
|
+
one chip.**
|
|
5
|
+
|
|
6
|
+
A job on a torus-connected pod does not need chips. It needs a *rectangle* --- an
|
|
7
|
+
axis-aligned sub-grid, because that is the only shape whose diameter, bisection
|
|
8
|
+
and collective schedule anyone has computed. That one constraint turns four
|
|
9
|
+
ordinary operational questions into different questions than the ones capacity
|
|
10
|
+
reports answer:
|
|
11
|
+
|
|
12
|
+
| The question people ask | The question that decides the outcome |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| How many chips are free? | How large a job can still be placed? |
|
|
15
|
+
| What does a chip failure cost? | *Where* did the chip fail? |
|
|
16
|
+
| Can we recover automatically? | What does waiting for a human cost? |
|
|
17
|
+
| Can tenants be isolated? | Which requests make isolation impossible? |
|
|
18
|
+
|
|
19
|
+
Six geometric models, one measured failure history, a command line, and a
|
|
20
|
+
validation registry that prints what it declines to check before it prints
|
|
21
|
+
anything it does check.
|
|
22
|
+
|
|
23
|
+
**There is exactly one measurement in this repository** --- the Titan failure
|
|
24
|
+
history the hazard model reads. The geometry has no empirical anchor. See
|
|
25
|
+
[What this does not check](#what-this-does-not-check).
|
|
26
|
+
|
|
27
|
+
## Seven findings
|
|
28
|
+
|
|
29
|
+
**1. A pod described as a torus hands most jobs a mesh.** A slice inherits a
|
|
30
|
+
closed ring in a dimension only if it spans that dimension *completely*. Over
|
|
31
|
+
485 slices placed at random on a 16-ary 3-cube, not one received a
|
|
32
|
+
three-dimensional torus, and every slice lost at least one ring. The wraparound belongs to the pod; the job gets what is left.
|
|
33
|
+
|
|
34
|
+
**2. Free chips overstate capacity, and the gap widens as the pod fills.**
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
occupancy free placeable overstated trials with a gap
|
|
38
|
+
10% 3,217 2,953 8% 31/60
|
|
39
|
+
40% 2,131 1,696 20% 51/60
|
|
40
|
+
55% 1,547 1,090 30% 55/60
|
|
41
|
+
85% 634 448 29% 41/60
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**3. One chip failure costs between 6% and 50% of a slice, depending on where
|
|
45
|
+
it was.** Getting back to a rectangle means pulling a face in past the failure.
|
|
46
|
+
A corner costs one plane; the centre costs half the slice.
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
where coordinate chips lost share
|
|
50
|
+
corner (0, 0, 0) 256 6.2%
|
|
51
|
+
face (0, 8, 8) 256 6.2%
|
|
52
|
+
interior (4, 8, 8) 1,280 31.2%
|
|
53
|
+
centre (8, 8, 8) 2,048 50.0%
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The worst case is **exactly half the slice for every shape**, so packing cannot
|
|
57
|
+
buy it down. The best case is `chips / longest axis` --- which means the compact
|
|
58
|
+
shape that wins on diameter is the one with the *highest* typical failure cost.
|
|
59
|
+
At 4,096 chips in a 64-ary pod, the compact `16x16x16` loses 256 chips to its
|
|
60
|
+
cheapest failure and the flat `1x64x64` loses 64.
|
|
61
|
+
|
|
62
|
+
**4. The option that keeps your checkpoint is the one that runs out first.**
|
|
63
|
+
Shrinking in place is cheap in hardware and breaks the rank grid, so the
|
|
64
|
+
checkpoint no longer restores. Moving at the same shape keeps the checkpoint and
|
|
65
|
+
costs other tenants their chips. Of 120 simulated failures a shrink existed in
|
|
66
|
+
all 120 and a same-shape move in only 97.
|
|
67
|
+
|
|
68
|
+
**5. Isolation has a price, and one request it cannot fill at any price.**
|
|
69
|
+
Dedicating a rack per tenant admitted 40,000 chips where an open pod took
|
|
70
|
+
75,392. And a job that wants a closed ring must span the axis, which means
|
|
71
|
+
touching every rack in it --- so "give me a torus" and "keep me off other
|
|
72
|
+
tenants' hardware" are contradictory, not merely competing.
|
|
73
|
+
|
|
74
|
+
**6. The approval queue becomes the outage exactly when the pod is busiest.**
|
|
75
|
+
Confining autonomous action to the failing job means anything that evicts a
|
|
76
|
+
neighbour needs a person. Share of failures that reach that boundary:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
occupancy 25%: 0/40 50%: 0/40 75%: 5/40 95%: 38/40
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`cost_of_waiting` prints what the L1 action gives up against the best action
|
|
83
|
+
available, and returns `None` --- never zero --- when there is no autonomous
|
|
84
|
+
action at all.
|
|
85
|
+
|
|
86
|
+
**7. On the one measured fleet, hazard-ranked *placement* pays and hazard-ranked
|
|
87
|
+
*eviction* does not.** New in 1.1: `hazard` reads the public Titan GPU lifetime
|
|
88
|
+
dataset --- 30,207 GPUs, 100,889 GPU-years (Ostrouchov et al., SC '20), fetched
|
|
89
|
+
and SHA-pinned by `make data`. Deaths per GPU-year climb 0.0009 → 0.0082 →
|
|
90
|
+
0.119 → 0.134 across the old batch's first four years (no infant mortality ---
|
|
91
|
+
the first year is the safest), and order 0.034 → 0.071 → 0.115 by cage, bottom
|
|
92
|
+
of the cooling path to top. Rank held-out chips by cohort hazard learned on the
|
|
93
|
+
other half of the fleet and the top 30% hold 55% of the deaths (lift 1.84×).
|
|
94
|
+
But price a preemptive drain against an unplanned reconstitution and even the
|
|
95
|
+
worst cohort rides unless the drain costs under ~3% of the rebuild: the
|
|
96
|
+
break-even hazard at a 90-day window and a 4:1 cost ratio is 1.17/GPU-year,
|
|
97
|
+
nearly nine times anything the fleet ever measured. Titan's operators reached the same
|
|
98
|
+
verdict in production: they re-cut the job mix onto reliable nodes; they did
|
|
99
|
+
not evict ahead of failure. The rates are Titan's own and do not transfer
|
|
100
|
+
(ASSUMPTIONS A12); the shape --- cohort beats fleet-uniform --- is the claim.
|
|
101
|
+
|
|
102
|
+
## Quickstart
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
make venv
|
|
106
|
+
make smoke-test # tests, registry and examples, under a minute
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
slicepacker example # the reference scenario end to end
|
|
111
|
+
slicepacker shapes 4096 -k 64 -n 3 # legal shapes, and which objective picks which
|
|
112
|
+
slicepacker cordon --shape 16,16,16 # what one chip costs, best to worst
|
|
113
|
+
slicepacker pack examples/pod-fragmented.json
|
|
114
|
+
slicepacker isolate examples/tenants-contradictory.json
|
|
115
|
+
slicepacker reconstitute examples/failure-no-room.json pretrain-7 4,8,8
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Exit codes are part of the interface: `0` answered, `1` **refused**, `2` the
|
|
119
|
+
input could not be read. A refusal is a correct answer, and a scheduler that
|
|
120
|
+
treats it as an error papers over the conditions this tool exists to surface.
|
|
121
|
+
|
|
122
|
+
## The models
|
|
123
|
+
|
|
124
|
+
| Module | What it decides |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `torus` | k-ary n-cube diameter and bisection; whether a slice inherits a ring |
|
|
127
|
+
| `packing` | placement, fragmentation, the largest job still placeable |
|
|
128
|
+
| `cordon` | what it costs to get back to a rectangle after a chip dies |
|
|
129
|
+
| `embed` | shrink versus move, and the drain a move requires |
|
|
130
|
+
| `tenant` | blast-domain isolation, its price, and its contradictions |
|
|
131
|
+
| `reconstitute` | what a control plane may do alone, and what waiting costs |
|
|
132
|
+
| `hazard` | when a chip earns eviction before it fails, measured on the Titan fleet |
|
|
133
|
+
|
|
134
|
+
`docs/the-models.md` explains each in prose. `docs/integration.md` covers
|
|
135
|
+
wiring it to a scheduler.
|
|
136
|
+
|
|
137
|
+
## What this does not check
|
|
138
|
+
|
|
139
|
+
The validation registry prints sixteen declined items above its results on
|
|
140
|
+
every run. The first two matter most:
|
|
141
|
+
|
|
142
|
+
> No measured **packing**. Every geometry number here is a model output:
|
|
143
|
+
> nothing has been compared against a real torus pod or a real scheduler. The
|
|
144
|
+
> one measured thing is the **failure history** the hazard module reads, and
|
|
145
|
+
> it anchors failure rates only --- not one packing figure.
|
|
146
|
+
|
|
147
|
+
> The calibrated points pin textbook **closed forms**, which are identities
|
|
148
|
+
> about an idealised k-ary n-cube. Agreeing with them shows this code implements
|
|
149
|
+
> the model correctly. It is not evidence that the model describes any machine.
|
|
150
|
+
> The Titan points are the only cells anchored to a measured fleet --- and they
|
|
151
|
+
> anchor the *failure process*, not one packing figure.
|
|
152
|
+
|
|
153
|
+
Also declined: link failures, routing, time, correlated failure, non-rectangular
|
|
154
|
+
allocation, the reshard cost model, the L0/L1 boundary itself, first-fit
|
|
155
|
+
placement, what a rack is, the cost of refusing seam-straddling slices, the
|
|
156
|
+
paper's filtered device-level counts (the summary file cannot express them),
|
|
157
|
+
any transfer of Titan's rates to another machine, and repeated-play eviction.
|
|
158
|
+
|
|
159
|
+
The mutation tests in `tests/test_mutations.py` delete machinery on purpose and
|
|
160
|
+
assert the exact set of registry points that turns red. Nineteen mutations, a
|
|
161
|
+
green unmutated control so no red set can be an artefact, and two tests that
|
|
162
|
+
apply a real change and assert the registry does **not** notice --- because on
|
|
163
|
+
the geometry side it genuinely cannot. One Titan mutation earned its point a
|
|
164
|
+
sharper assertion: dropping the exposure clamp preserved every ordering and
|
|
165
|
+
first went red only once the mid-life magnitude was pinned. Every asserted red set was measured. Predicting them first was
|
|
166
|
+
wrong nine times out of seventeen, and two of those surprises were points that
|
|
167
|
+
had been passing on machinery that was no longer there.
|
|
168
|
+
|
|
169
|
+
## Reproducing
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
make data # fetch + SHA-verify the Titan dataset (once; ~4 MB)
|
|
173
|
+
make test # 104 unit tests and 22 mutation tests (~5 min: each mutation reruns the registry)
|
|
174
|
+
make validate # 29 registry points and 16 declined items
|
|
175
|
+
make examples # 24 examples, each pinned to its exit code
|
|
176
|
+
make experiments # the three figures quoted above; each exits 1 if it stops holding
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Reading order
|
|
180
|
+
|
|
181
|
+
- `DECISIONS.md` --- sixteen choices, what each bought and cost. Six were
|
|
182
|
+
forced by defects found while building this, and say so.
|
|
183
|
+
- `ASSUMPTIONS.md` --- twelve things taken as given.
|
|
184
|
+
- `SOURCES.md` --- three, and what they are and are not.
|
|
185
|
+
- `STATUS.md` --- what works, what is missing, what would change the answers.
|
|
186
|
+
|
|
187
|
+
## Series
|
|
188
|
+
|
|
189
|
+
Part of a program on the usable capacity of large accelerator fleets:
|
|
190
|
+
[dimaggi-ai.github.io/research](https://dimaggi-ai.github.io/research).
|
|
191
|
+
|
|
192
|
+
## Licence
|
|
193
|
+
|
|
194
|
+
MIT. Copyright (c) 2026 Margaret Nanyonga.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "slice-packer-torus"
|
|
7
|
+
version = "1.1.0"
|
|
8
|
+
description = "What a torus pod can actually still admit, what a chip failure costs, and who is allowed to fix it"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Margaret Nanyonga" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"torus",
|
|
15
|
+
"k-ary n-cube",
|
|
16
|
+
"capacity planning",
|
|
17
|
+
"fragmentation",
|
|
18
|
+
"multi-tenancy",
|
|
19
|
+
"fault domains",
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Intended Audience :: Science/Research",
|
|
23
|
+
"Intended Audience :: System Administrators",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Scientific/Engineering",
|
|
27
|
+
"Topic :: System :: Distributed Computing",
|
|
28
|
+
]
|
|
29
|
+
dependencies = []
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = ["pytest==8.3.4"]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/dimaggi-ai/slice-packer-torus"
|
|
36
|
+
Research = "https://dimaggi-ai.github.io/research"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
slicepacker = "slicepacker.cli:main"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
where = ["src"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
testpaths = ["tests"]
|
|
46
|
+
pythonpath = ["src", "validation"]
|
|
47
|
+
addopts = "-q"
|