flashruntime 0.3.0__py3-none-any.whl
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.
- flashml_workloads/__init__.py +7 -0
- flashml_workloads/fedavg_driver.py +569 -0
- flashml_workloads/fedavg_weights.py +223 -0
- flashml_workloads/fedavg_worker.py +166 -0
- flashml_workloads/kmeans_driver.py +134 -0
- flashml_workloads/kmeans_shard.py +69 -0
- flashml_workloads/sgd_trainer.py +127 -0
- flashml_workloads/sharded_kmeans.py +323 -0
- flashml_workloads/sklearn_trial.py +89 -0
- flashruntime/__init__.py +125 -0
- flashruntime/artifacts/__init__.py +25 -0
- flashruntime/artifacts/store.py +228 -0
- flashruntime/backends/__init__.py +26 -0
- flashruntime/backends/base.py +63 -0
- flashruntime/backends/kuberay.py +465 -0
- flashruntime/checkpoint/__init__.py +20 -0
- flashruntime/checkpoint/catalog.py +198 -0
- flashruntime/checkpoint/local.py +109 -0
- flashruntime/checkpoint/store.py +86 -0
- flashruntime/integrations/__init__.py +5 -0
- flashruntime/integrations/huggingface.py +59 -0
- flashruntime/integrations/pytorch.py +52 -0
- flashruntime/integrations/sklearn.py +42 -0
- flashruntime/launchers/__init__.py +130 -0
- flashruntime/launchers/local.py +126 -0
- flashruntime/leases/__init__.py +27 -0
- flashruntime/leases/manager.py +365 -0
- flashruntime/leases/sqlite_store.py +169 -0
- flashruntime/leases/store.py +103 -0
- flashruntime/monitor/__init__.py +7 -0
- flashruntime/monitor/sampler.py +232 -0
- flashruntime/planner/__init__.py +56 -0
- flashruntime/planner/candidates.py +597 -0
- flashruntime/planner/catalog.py +129 -0
- flashruntime/planner/comm.py +95 -0
- flashruntime/planner/explain.py +109 -0
- flashruntime/planner/memory.py +166 -0
- flashruntime/planner/resolve.py +120 -0
- flashruntime/planner/selector.py +169 -0
- flashruntime/planner/timecost.py +81 -0
- flashruntime/profiling/__init__.py +113 -0
- flashruntime/protocol/__init__.py +18 -0
- flashruntime/protocol/plan_v1alpha1.py +320 -0
- flashruntime/protocol/v1alpha1.py +465 -0
- flashruntime/providers/__init__.py +138 -0
- flashruntime/py.typed +0 -0
- flashruntime/recipes/__init__.py +135 -0
- flashruntime/recipes/command.py +166 -0
- flashruntime/recovery/__init__.py +21 -0
- flashruntime/recovery/policy.py +170 -0
- flashruntime/recovery/signals.py +135 -0
- flashruntime/recovery/taxonomy.py +91 -0
- flashruntime/scheduler/__init__.py +170 -0
- flashruntime/sdk.py +402 -0
- flashruntime/service/__init__.py +3 -0
- flashruntime/service/app.py +391 -0
- flashruntime/service/auth.py +180 -0
- flashruntime/service/checkpoints.py +90 -0
- flashruntime/service/cli.py +167 -0
- flashruntime/service/dashboard.py +193 -0
- flashruntime/service/ledger.py +101 -0
- flashruntime/service/modea.py +821 -0
- flashruntime/strategies/__init__.py +156 -0
- flashruntime/strategies/command.py +56 -0
- flashruntime/torch/__init__.py +274 -0
- flashruntime/viewer/__init__.py +20 -0
- flashruntime/viewer/_docs/benchmarks.html +771 -0
- flashruntime/viewer/_docs/concepts/architecture.html +302 -0
- flashruntime/viewer/_docs/get-started.html +263 -0
- flashruntime/viewer/_docs/guides/federated-averaging.html +363 -0
- flashruntime/viewer/_docs/guides/huggingface.html +223 -0
- flashruntime/viewer/_docs/guides/jobspec-and-isolation.html +271 -0
- flashruntime/viewer/_docs/guides/pytorch.html +313 -0
- flashruntime/viewer/_docs/guides/sklearn.html +232 -0
- flashruntime/viewer/_docs/index.html +251 -0
- flashruntime/viewer/_docs/reference/cli.html +254 -0
- flashruntime/viewer/_docs/reference/integrations.html +240 -0
- flashruntime/viewer/_docs/reference/sdk.html +341 -0
- flashruntime/viewer/_docs/reference/torch-helper.html +244 -0
- flashruntime/viewer/_docs/search-index.json +1 -0
- flashruntime/viewer/_docs/tutorials/convnet.html +571 -0
- flashruntime/viewer/_docs/tutorials/fault-tolerance.html +375 -0
- flashruntime/viewer/_docs/tutorials/sklearn-sweeps.html +278 -0
- flashruntime/viewer/flowmap.py +307 -0
- flashruntime/viewer/page.py +594 -0
- flashruntime/viewer/server.py +134 -0
- flashruntime/viewer/state.py +250 -0
- flashruntime/workloads/__init__.py +6 -0
- flashruntime/workloads/command.py +127 -0
- flashruntime-0.3.0.dist-info/METADATA +365 -0
- flashruntime-0.3.0.dist-info/RECORD +95 -0
- flashruntime-0.3.0.dist-info/WHEEL +5 -0
- flashruntime-0.3.0.dist-info/entry_points.txt +2 -0
- flashruntime-0.3.0.dist-info/licenses/LICENSE +202 -0
- flashruntime-0.3.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Reference: CLI (`flashruntime`) — flashruntime docs</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root { color-scheme: dark; }
|
|
9
|
+
* { box-sizing: border-box; margin: 0; }
|
|
10
|
+
body { font: 14px/1.65 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; background: #0d1117; color: #c9d1d9; }
|
|
11
|
+
a { color: oklch(0.80 0.16 200); text-decoration: none; }
|
|
12
|
+
a:hover { text-decoration: underline; }
|
|
13
|
+
.layout { display: flex; align-items: flex-start; min-height: 100vh; }
|
|
14
|
+
|
|
15
|
+
/* sidebar — PyTorch-docs-like: sections from _nav.yml, current page active */
|
|
16
|
+
.sidebar { flex: 0 0 264px; position: sticky; top: 0; height: 100vh; overflow-y: auto;
|
|
17
|
+
border-right: 1px solid #21262d; background: #0d1117; padding: 20px 16px; }
|
|
18
|
+
.brand { color: #e6edf3; font-size: 15px; letter-spacing: .04em; }
|
|
19
|
+
.brand small { display: block; margin-top: 2px; color: #8b949e; font-size: 10px;
|
|
20
|
+
text-transform: uppercase; letter-spacing: .14em; }
|
|
21
|
+
.search { position: relative; margin: 16px 0; }
|
|
22
|
+
#q { width: 100%; background: #010409; border: 1px solid #21262d; border-radius: 6px;
|
|
23
|
+
color: #c9d1d9; font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; padding: 7px 9px; }
|
|
24
|
+
#q:focus { outline: 1px solid oklch(0.80 0.16 200); }
|
|
25
|
+
#results { position: absolute; left: 0; right: 0; top: 112%; z-index: 5; display: none;
|
|
26
|
+
background: #161b22; border: 1px solid #21262d; border-radius: 6px; overflow: hidden; }
|
|
27
|
+
#results.open { display: block; }
|
|
28
|
+
#results a { display: block; padding: 7px 9px; border-bottom: 1px solid #21262d; color: #c9d1d9; }
|
|
29
|
+
#results a:last-child { border-bottom: 0; }
|
|
30
|
+
#results a:hover { background: #010409; text-decoration: none; }
|
|
31
|
+
#results a b { color: #e6edf3; font-weight: 600; }
|
|
32
|
+
#results a span { display: block; margin-top: 2px; color: #8b949e; font-size: 11px; }
|
|
33
|
+
#results .nohit { padding: 7px 9px; color: #8b949e; }
|
|
34
|
+
.nav-section { margin: 16px 0 6px; color: #8b949e; font-size: 10px; font-weight: 600;
|
|
35
|
+
text-transform: uppercase; letter-spacing: .14em; }
|
|
36
|
+
.nav-link { display: block; padding: 4px 8px; border-radius: 5px; color: #c9d1d9; font-size: 13px; }
|
|
37
|
+
.nav-link:hover { background: #161b22; text-decoration: none; }
|
|
38
|
+
.nav-link.active { background: #161b22; color: #e6edf3; box-shadow: inset 2px 0 0 oklch(0.80 0.16 200); }
|
|
39
|
+
|
|
40
|
+
/* content */
|
|
41
|
+
.content { flex: 1 1 auto; max-width: 840px; min-width: 0; padding: 34px 40px 80px; }
|
|
42
|
+
.content h1 { color: #e6edf3; font-size: 26px; margin: 0 0 16px; }
|
|
43
|
+
.content h2 { color: #e6edf3; font-size: 18px; margin: 30px 0 10px;
|
|
44
|
+
padding-top: 10px; border-top: 1px solid #21262d; }
|
|
45
|
+
.content h3 { color: #e6edf3; font-size: 15px; margin: 22px 0 8px; }
|
|
46
|
+
.content p, .content li { color: #c9d1d9; }
|
|
47
|
+
.content ul, .content ol { padding-left: 22px; margin: 10px 0; }
|
|
48
|
+
.content li { margin: 4px 0; }
|
|
49
|
+
.content blockquote { margin: 14px 0; padding: 2px 14px; border-left: 3px solid oklch(0.80 0.18 60);
|
|
50
|
+
background: #161b22; border-radius: 0 6px 6px 0; color: #8b949e; }
|
|
51
|
+
.content :not(pre) > code { background: #010409; border: 1px solid #21262d;
|
|
52
|
+
border-radius: 4px; padding: 1px 5px; font-size: 12.5px; }
|
|
53
|
+
.content table { border-collapse: collapse; margin: 14px 0; display: block; overflow-x: auto; }
|
|
54
|
+
.content th, .content td { border: 1px solid #21262d; padding: 6px 10px; text-align: left; }
|
|
55
|
+
.content th { color: #e6edf3; background: #161b22; }
|
|
56
|
+
|
|
57
|
+
/* code blocks + copy button */
|
|
58
|
+
.codeblock { position: relative; margin: 14px 0; }
|
|
59
|
+
.codeblock pre { background: #010409; border: 1px solid #21262d; border-radius: 8px;
|
|
60
|
+
padding: 14px 16px; overflow-x: auto; }
|
|
61
|
+
.codeblock pre code { padding: 0; border: 0; background: none; font-size: 12.5px; color: #c9d1d9; }
|
|
62
|
+
.copybtn { position: absolute; top: 8px; right: 8px; padding: 3px 8px; cursor: pointer;
|
|
63
|
+
background: #161b22; border: 1px solid #21262d; border-radius: 5px;
|
|
64
|
+
color: #8b949e; font: 11px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
65
|
+
.copybtn:hover { color: #e6edf3; border-color: oklch(0.80 0.16 200); }
|
|
66
|
+
|
|
67
|
+
@media (max-width: 800px) {
|
|
68
|
+
.layout { flex-direction: column; }
|
|
69
|
+
.sidebar { position: static; height: auto; width: 100%; flex-basis: auto;
|
|
70
|
+
border-right: 0; border-bottom: 1px solid #21262d; }
|
|
71
|
+
.content { padding: 24px 18px 60px; }
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<div class="layout">
|
|
77
|
+
<aside class="sidebar">
|
|
78
|
+
<a class="brand" href="../index.html">flashruntime<small>documentation</small></a>
|
|
79
|
+
<div class="search">
|
|
80
|
+
<input id="q" type="search" placeholder="Search docs (press /)" autocomplete="off" spellcheck="false">
|
|
81
|
+
<div id="results"></div>
|
|
82
|
+
</div>
|
|
83
|
+
<nav><div class="nav-section">Getting started</div>
|
|
84
|
+
<a class="nav-link" href="../index.html">FlashRuntime</a>
|
|
85
|
+
<a class="nav-link" href="../get-started.html">Get started</a>
|
|
86
|
+
<div class="nav-section">Tutorials</div>
|
|
87
|
+
<a class="nav-link" href="../tutorials/convnet.html">Tutorial: make a ConvNet fault-tolerant</a>
|
|
88
|
+
<a class="nav-link" href="../tutorials/sklearn-sweeps.html">Tutorial: parallel scikit-learn sweeps</a>
|
|
89
|
+
<a class="nav-link" href="../tutorials/fault-tolerance.html">Tutorial: automatic recovery, explained</a>
|
|
90
|
+
<div class="nav-section">Guides</div>
|
|
91
|
+
<a class="nav-link" href="../guides/pytorch.html">PyTorch guide</a>
|
|
92
|
+
<a class="nav-link" href="../guides/sklearn.html">scikit-learn guide</a>
|
|
93
|
+
<a class="nav-link" href="../guides/huggingface.html">Hugging Face guide</a>
|
|
94
|
+
<a class="nav-link" href="../guides/jobspec-and-isolation.html">JobSpec & isolation guide</a>
|
|
95
|
+
<a class="nav-link" href="../guides/federated-averaging.html">Federated averaging</a>
|
|
96
|
+
<div class="nav-section">Concepts</div>
|
|
97
|
+
<a class="nav-link" href="../concepts/architecture.html">Architecture</a>
|
|
98
|
+
<div class="nav-section">Reference</div>
|
|
99
|
+
<a class="nav-link" href="sdk.html">Reference: SDK (`flashruntime`)</a>
|
|
100
|
+
<a class="nav-link" href="integrations.html">Reference: integrations (`flashruntime.integrations`)</a>
|
|
101
|
+
<a class="nav-link" href="torch-helper.html">Reference: torch helper (`flashruntime.torch`)</a>
|
|
102
|
+
<a class="nav-link active" href="cli.html">Reference: CLI (`flashruntime`)</a>
|
|
103
|
+
<div class="nav-section">Benchmarks</div>
|
|
104
|
+
<a class="nav-link" href="../benchmarks.html">Benchmarks</a></nav>
|
|
105
|
+
</aside>
|
|
106
|
+
<main class="content"><h1 id="reference-cli-flashruntime">Reference: CLI (<code>flashruntime</code>)</h1>
|
|
107
|
+
<p>The <code>flashruntime</code> command ships with the <code>[service]</code> extra
|
|
108
|
+
(<code>pip install "flashruntime[service]"</code>). It is the terminal front door to the
|
|
109
|
+
same operations the SDK exposes: plan a job offline, run a command workload
|
|
110
|
+
locally, and talk to a coordinator.</p>
|
|
111
|
+
<p>The blocks below mirror the real <code>--help</code> output.</p>
|
|
112
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code>usage: flashruntime [-h] [--api API]
|
|
113
|
+
{plan,submit,submit-spec,status,events,logs,cancel} ...
|
|
114
|
+
|
|
115
|
+
positional arguments:
|
|
116
|
+
{plan,submit,submit-spec,status,events,logs,cancel}
|
|
117
|
+
plan evaluate a PlanRequest offline and print the strategy
|
|
118
|
+
submit run a command workload locally (no API needed)
|
|
119
|
+
submit-spec POST a JobSpec YAML to the coordinator — was `submit`
|
|
120
|
+
before 0.1.0; renamed when `submit` became the local-
|
|
121
|
+
workload front door
|
|
122
|
+
|
|
123
|
+
options:
|
|
124
|
+
-h, --help show this help message and exit
|
|
125
|
+
--api API FlashRuntime API base URL
|
|
126
|
+
</code></pre></div>
|
|
127
|
+
<p><code>--api</code> names the coordinator base URL for the service-side subcommands
|
|
128
|
+
(<code>submit-spec</code>, <code>status</code>, <code>events</code>, <code>logs</code>, <code>cancel</code>).</p>
|
|
129
|
+
<hr />
|
|
130
|
+
<h2 id="plan-offline-strategy-selection"><code>plan</code> — offline strategy selection</h2>
|
|
131
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code>usage: flashruntime plan [-h] [--json] request_file
|
|
132
|
+
|
|
133
|
+
positional arguments:
|
|
134
|
+
request_file PlanRequest as .yaml or .json
|
|
135
|
+
|
|
136
|
+
options:
|
|
137
|
+
-h, --help show this help message and exit
|
|
138
|
+
--json emit the full PlanReport as JSON
|
|
139
|
+
</code></pre></div>
|
|
140
|
+
<p>Runs <code>flash.plan()</code> on a <code>PlanRequest</code> file and prints the explained strategy;
|
|
141
|
+
<code>--json</code> emits the full <code>PlanReport</code>. No cluster required.</p>
|
|
142
|
+
<hr />
|
|
143
|
+
<h2 id="submit-run-a-command-workload-locally"><code>submit</code> — run a command workload locally</h2>
|
|
144
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code>usage: flashruntime submit [-h] [--source SOURCE] [--task-params TASK_PARAMS]
|
|
145
|
+
[--max-restarts MAX_RESTARTS]
|
|
146
|
+
[--output-dir OUTPUT_DIR] [--watch | --no-watch]
|
|
147
|
+
CMD
|
|
148
|
+
|
|
149
|
+
positional arguments:
|
|
150
|
+
CMD the command to run, e.g. 'python train.py --lr {lr}'
|
|
151
|
+
|
|
152
|
+
options:
|
|
153
|
+
-h, --help show this help message and exit
|
|
154
|
+
--source SOURCE directory holding the user's code
|
|
155
|
+
--task-params TASK_PARAMS
|
|
156
|
+
JSON list of param dicts for Mode A fan-out
|
|
157
|
+
--max-restarts MAX_RESTARTS
|
|
158
|
+
automatic recovery budget
|
|
159
|
+
--output-dir OUTPUT_DIR
|
|
160
|
+
where run.json and artifacts land (default: temp dir)
|
|
161
|
+
--watch, --no-watch open the live viewer (default: on at a terminal, off
|
|
162
|
+
in pipes/CI)
|
|
163
|
+
</code></pre></div>
|
|
164
|
+
<p>The terminal equivalent of <code>flash.submit()</code>. <code>--task-params</code> (a JSON list of
|
|
165
|
+
param dicts) fills <code>{name}</code> placeholders in <code>CMD</code> for a fan-out sweep;
|
|
166
|
+
<code>--max-restarts</code> is the automatic fault-tolerance budget.</p>
|
|
167
|
+
<hr />
|
|
168
|
+
<h2 id="submit-spec-post-a-jobspec-to-the-coordinator"><code>submit-spec</code> — POST a JobSpec to the coordinator</h2>
|
|
169
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code>usage: flashruntime submit-spec [-h] spec_file
|
|
170
|
+
|
|
171
|
+
positional arguments:
|
|
172
|
+
spec_file
|
|
173
|
+
|
|
174
|
+
options:
|
|
175
|
+
-h, --help show this help message and exit
|
|
176
|
+
</code></pre></div>
|
|
177
|
+
<p>POSTs a <code>JobSpec</code> YAML/JSON file (e.g. one produced by
|
|
178
|
+
<code>workloads.command.to_jobspec</code>) to the coordinator named by <code>--api</code>. This was
|
|
179
|
+
called <code>submit</code> before 0.1.0 — it was renamed when local <code>submit</code> became the
|
|
180
|
+
default front door.</p>
|
|
181
|
+
<hr />
|
|
182
|
+
<h2 id="status-events-logs-cancel-inspect-a-coordinator-job"><code>status</code> / <code>events</code> / <code>logs</code> / <code>cancel</code> — inspect a coordinator job</h2>
|
|
183
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code>usage: flashruntime status [-h] job_id
|
|
184
|
+
usage: flashruntime events [-h] job_id
|
|
185
|
+
usage: flashruntime logs [-h] job_id
|
|
186
|
+
usage: flashruntime cancel [-h] job_id
|
|
187
|
+
</code></pre></div>
|
|
188
|
+
<p>Each takes a <code>job_id</code> and queries the coordinator at <code>--api</code>: <code>status</code> for the
|
|
189
|
+
derived job state, <code>events</code> for the append-only ledger, <code>logs</code> for captured
|
|
190
|
+
output, and <code>cancel</code> to stop a job.</p>
|
|
191
|
+
<hr />
|
|
192
|
+
<p>See the <a href="../guides/jobspec-and-isolation.html">JobSpec & isolation guide</a> for the
|
|
193
|
+
wire form these service subcommands operate on, and the <a href="sdk.html">SDK reference</a>
|
|
194
|
+
for the in-process equivalents.</p></main>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<script>
|
|
198
|
+
// ---- client-side search: fetch the builder's index, filter as you type -----
|
|
199
|
+
// (<=60 lines, vanilla JS, no external anything — the index is a sibling file.)
|
|
200
|
+
let INDEX = [];
|
|
201
|
+
// Path from THIS page back to the site root. The index stores root-relative
|
|
202
|
+
// URLs (e.g. "tutorials/deep.html"); we fetch it and build result links
|
|
203
|
+
// against ROOT so a page in a subdir resolves them too (see build_docs.py).
|
|
204
|
+
const ROOT = "../";
|
|
205
|
+
const q = document.getElementById("q");
|
|
206
|
+
const results = document.getElementById("results");
|
|
207
|
+
const esc = (s) => String(s).replace(/[&<>"]/g, (c) =>
|
|
208
|
+
({ "&": "&", "<": "<", ">": ">", '"': """ }[c]));
|
|
209
|
+
fetch(ROOT + "search-index.json").then((r) => r.json()).then((d) => { INDEX = d; }).catch(() => {});
|
|
210
|
+
|
|
211
|
+
// A short context window around the first match, so a hit shows WHY it matched.
|
|
212
|
+
function snippet(text, needle) {
|
|
213
|
+
const i = text.toLowerCase().indexOf(needle);
|
|
214
|
+
if (i < 0) return "";
|
|
215
|
+
const start = Math.max(0, i - 32);
|
|
216
|
+
return (start > 0 ? "…" : "") + text.slice(start, i + needle.length + 44).trim() + "…";
|
|
217
|
+
}
|
|
218
|
+
function runSearch() {
|
|
219
|
+
const needle = q.value.trim().toLowerCase();
|
|
220
|
+
if (!needle) { results.className = ""; results.innerHTML = ""; return; }
|
|
221
|
+
const hits = INDEX.map((p) => {
|
|
222
|
+
const inTitle = p.title.toLowerCase().includes(needle);
|
|
223
|
+
const inText = p.text.toLowerCase().includes(needle);
|
|
224
|
+
if (!inTitle && !inText) return null;
|
|
225
|
+
return { url: p.url, title: p.title, snip: inText ? snippet(p.text, needle) : "" };
|
|
226
|
+
}).filter(Boolean).slice(0, 20);
|
|
227
|
+
results.className = "open";
|
|
228
|
+
results.innerHTML = hits.length
|
|
229
|
+
? hits.map((h) => '<a href="' + ROOT + h.url + '"><b>' + esc(h.title) + "</b>" +
|
|
230
|
+
(h.snip ? "<span>" + esc(h.snip) + "</span>" : "") + "</a>").join("")
|
|
231
|
+
: '<div class="nohit">no matches</div>';
|
|
232
|
+
}
|
|
233
|
+
q.addEventListener("input", runSearch);
|
|
234
|
+
q.addEventListener("focus", runSearch);
|
|
235
|
+
document.addEventListener("click", (e) => {
|
|
236
|
+
if (!e.target.closest(".search")) { results.className = ""; } // dismiss on outside click
|
|
237
|
+
});
|
|
238
|
+
document.addEventListener("keydown", (e) => { // "/" focuses search, like PyTorch docs
|
|
239
|
+
if (e.key === "/" && document.activeElement !== q) { e.preventDefault(); q.focus(); }
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// ---- copy buttons: read the <pre>'s own text into the clipboard ------------
|
|
243
|
+
document.querySelectorAll(".copybtn").forEach((btn) => {
|
|
244
|
+
btn.addEventListener("click", () => {
|
|
245
|
+
const code = btn.parentElement.querySelector("pre").innerText;
|
|
246
|
+
navigator.clipboard.writeText(code).then(() => {
|
|
247
|
+
const was = btn.textContent; btn.textContent = "Copied";
|
|
248
|
+
setTimeout(() => { btn.textContent = was; }, 1200);
|
|
249
|
+
}).catch(() => {});
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
</script>
|
|
253
|
+
</body>
|
|
254
|
+
</html>
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Reference: integrations (`flashruntime.integrations`) — flashruntime docs</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root { color-scheme: dark; }
|
|
9
|
+
* { box-sizing: border-box; margin: 0; }
|
|
10
|
+
body { font: 14px/1.65 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; background: #0d1117; color: #c9d1d9; }
|
|
11
|
+
a { color: oklch(0.80 0.16 200); text-decoration: none; }
|
|
12
|
+
a:hover { text-decoration: underline; }
|
|
13
|
+
.layout { display: flex; align-items: flex-start; min-height: 100vh; }
|
|
14
|
+
|
|
15
|
+
/* sidebar — PyTorch-docs-like: sections from _nav.yml, current page active */
|
|
16
|
+
.sidebar { flex: 0 0 264px; position: sticky; top: 0; height: 100vh; overflow-y: auto;
|
|
17
|
+
border-right: 1px solid #21262d; background: #0d1117; padding: 20px 16px; }
|
|
18
|
+
.brand { color: #e6edf3; font-size: 15px; letter-spacing: .04em; }
|
|
19
|
+
.brand small { display: block; margin-top: 2px; color: #8b949e; font-size: 10px;
|
|
20
|
+
text-transform: uppercase; letter-spacing: .14em; }
|
|
21
|
+
.search { position: relative; margin: 16px 0; }
|
|
22
|
+
#q { width: 100%; background: #010409; border: 1px solid #21262d; border-radius: 6px;
|
|
23
|
+
color: #c9d1d9; font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; padding: 7px 9px; }
|
|
24
|
+
#q:focus { outline: 1px solid oklch(0.80 0.16 200); }
|
|
25
|
+
#results { position: absolute; left: 0; right: 0; top: 112%; z-index: 5; display: none;
|
|
26
|
+
background: #161b22; border: 1px solid #21262d; border-radius: 6px; overflow: hidden; }
|
|
27
|
+
#results.open { display: block; }
|
|
28
|
+
#results a { display: block; padding: 7px 9px; border-bottom: 1px solid #21262d; color: #c9d1d9; }
|
|
29
|
+
#results a:last-child { border-bottom: 0; }
|
|
30
|
+
#results a:hover { background: #010409; text-decoration: none; }
|
|
31
|
+
#results a b { color: #e6edf3; font-weight: 600; }
|
|
32
|
+
#results a span { display: block; margin-top: 2px; color: #8b949e; font-size: 11px; }
|
|
33
|
+
#results .nohit { padding: 7px 9px; color: #8b949e; }
|
|
34
|
+
.nav-section { margin: 16px 0 6px; color: #8b949e; font-size: 10px; font-weight: 600;
|
|
35
|
+
text-transform: uppercase; letter-spacing: .14em; }
|
|
36
|
+
.nav-link { display: block; padding: 4px 8px; border-radius: 5px; color: #c9d1d9; font-size: 13px; }
|
|
37
|
+
.nav-link:hover { background: #161b22; text-decoration: none; }
|
|
38
|
+
.nav-link.active { background: #161b22; color: #e6edf3; box-shadow: inset 2px 0 0 oklch(0.80 0.16 200); }
|
|
39
|
+
|
|
40
|
+
/* content */
|
|
41
|
+
.content { flex: 1 1 auto; max-width: 840px; min-width: 0; padding: 34px 40px 80px; }
|
|
42
|
+
.content h1 { color: #e6edf3; font-size: 26px; margin: 0 0 16px; }
|
|
43
|
+
.content h2 { color: #e6edf3; font-size: 18px; margin: 30px 0 10px;
|
|
44
|
+
padding-top: 10px; border-top: 1px solid #21262d; }
|
|
45
|
+
.content h3 { color: #e6edf3; font-size: 15px; margin: 22px 0 8px; }
|
|
46
|
+
.content p, .content li { color: #c9d1d9; }
|
|
47
|
+
.content ul, .content ol { padding-left: 22px; margin: 10px 0; }
|
|
48
|
+
.content li { margin: 4px 0; }
|
|
49
|
+
.content blockquote { margin: 14px 0; padding: 2px 14px; border-left: 3px solid oklch(0.80 0.18 60);
|
|
50
|
+
background: #161b22; border-radius: 0 6px 6px 0; color: #8b949e; }
|
|
51
|
+
.content :not(pre) > code { background: #010409; border: 1px solid #21262d;
|
|
52
|
+
border-radius: 4px; padding: 1px 5px; font-size: 12.5px; }
|
|
53
|
+
.content table { border-collapse: collapse; margin: 14px 0; display: block; overflow-x: auto; }
|
|
54
|
+
.content th, .content td { border: 1px solid #21262d; padding: 6px 10px; text-align: left; }
|
|
55
|
+
.content th { color: #e6edf3; background: #161b22; }
|
|
56
|
+
|
|
57
|
+
/* code blocks + copy button */
|
|
58
|
+
.codeblock { position: relative; margin: 14px 0; }
|
|
59
|
+
.codeblock pre { background: #010409; border: 1px solid #21262d; border-radius: 8px;
|
|
60
|
+
padding: 14px 16px; overflow-x: auto; }
|
|
61
|
+
.codeblock pre code { padding: 0; border: 0; background: none; font-size: 12.5px; color: #c9d1d9; }
|
|
62
|
+
.copybtn { position: absolute; top: 8px; right: 8px; padding: 3px 8px; cursor: pointer;
|
|
63
|
+
background: #161b22; border: 1px solid #21262d; border-radius: 5px;
|
|
64
|
+
color: #8b949e; font: 11px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
65
|
+
.copybtn:hover { color: #e6edf3; border-color: oklch(0.80 0.16 200); }
|
|
66
|
+
|
|
67
|
+
@media (max-width: 800px) {
|
|
68
|
+
.layout { flex-direction: column; }
|
|
69
|
+
.sidebar { position: static; height: auto; width: 100%; flex-basis: auto;
|
|
70
|
+
border-right: 0; border-bottom: 1px solid #21262d; }
|
|
71
|
+
.content { padding: 24px 18px 60px; }
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<div class="layout">
|
|
77
|
+
<aside class="sidebar">
|
|
78
|
+
<a class="brand" href="../index.html">flashruntime<small>documentation</small></a>
|
|
79
|
+
<div class="search">
|
|
80
|
+
<input id="q" type="search" placeholder="Search docs (press /)" autocomplete="off" spellcheck="false">
|
|
81
|
+
<div id="results"></div>
|
|
82
|
+
</div>
|
|
83
|
+
<nav><div class="nav-section">Getting started</div>
|
|
84
|
+
<a class="nav-link" href="../index.html">FlashRuntime</a>
|
|
85
|
+
<a class="nav-link" href="../get-started.html">Get started</a>
|
|
86
|
+
<div class="nav-section">Tutorials</div>
|
|
87
|
+
<a class="nav-link" href="../tutorials/convnet.html">Tutorial: make a ConvNet fault-tolerant</a>
|
|
88
|
+
<a class="nav-link" href="../tutorials/sklearn-sweeps.html">Tutorial: parallel scikit-learn sweeps</a>
|
|
89
|
+
<a class="nav-link" href="../tutorials/fault-tolerance.html">Tutorial: automatic recovery, explained</a>
|
|
90
|
+
<div class="nav-section">Guides</div>
|
|
91
|
+
<a class="nav-link" href="../guides/pytorch.html">PyTorch guide</a>
|
|
92
|
+
<a class="nav-link" href="../guides/sklearn.html">scikit-learn guide</a>
|
|
93
|
+
<a class="nav-link" href="../guides/huggingface.html">Hugging Face guide</a>
|
|
94
|
+
<a class="nav-link" href="../guides/jobspec-and-isolation.html">JobSpec & isolation guide</a>
|
|
95
|
+
<a class="nav-link" href="../guides/federated-averaging.html">Federated averaging</a>
|
|
96
|
+
<div class="nav-section">Concepts</div>
|
|
97
|
+
<a class="nav-link" href="../concepts/architecture.html">Architecture</a>
|
|
98
|
+
<div class="nav-section">Reference</div>
|
|
99
|
+
<a class="nav-link" href="sdk.html">Reference: SDK (`flashruntime`)</a>
|
|
100
|
+
<a class="nav-link active" href="integrations.html">Reference: integrations (`flashruntime.integrations`)</a>
|
|
101
|
+
<a class="nav-link" href="torch-helper.html">Reference: torch helper (`flashruntime.torch`)</a>
|
|
102
|
+
<a class="nav-link" href="cli.html">Reference: CLI (`flashruntime`)</a>
|
|
103
|
+
<div class="nav-section">Benchmarks</div>
|
|
104
|
+
<a class="nav-link" href="../benchmarks.html">Benchmarks</a></nav>
|
|
105
|
+
</aside>
|
|
106
|
+
<main class="content"><h1 id="reference-integrations-flashruntimeintegrations">Reference: integrations (<code>flashruntime.integrations</code>)</h1>
|
|
107
|
+
<p>Framework adapters that build a <code>CommandWorkload</code> for you. Each is a small,
|
|
108
|
+
framework-neutral function — the recipe axis of the four-axis architecture. No
|
|
109
|
+
adapter imports its framework at the top level (the import is paid only in your
|
|
110
|
+
training process).</p>
|
|
111
|
+
<p>Signatures below are exact; each entry says, in one line, <em>why it exists</em>.</p>
|
|
112
|
+
<hr />
|
|
113
|
+
<h2 id="integrationspytorch-fr_torch"><code>integrations.pytorch</code> (<code>fr_torch</code>)</h2>
|
|
114
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code class="language-python">def ddp(
|
|
115
|
+
script,
|
|
116
|
+
*,
|
|
117
|
+
source=".",
|
|
118
|
+
nproc_per_node=2,
|
|
119
|
+
nnodes=1,
|
|
120
|
+
script_args="",
|
|
121
|
+
env=None,
|
|
122
|
+
) -> CommandWorkload: ...
|
|
123
|
+
</code></pre></div>
|
|
124
|
+
<p>Builds the <code>torchrun</code> launch command for a PyTorch script — the launch
|
|
125
|
+
conventions only; DDP is wired by your code (or <code>flashruntime.torch.prepare</code>).
|
|
126
|
+
Emits <code>torchrun --nproc-per-node=N --nnodes=1 --standalone
|
|
127
|
+
--local-addr=127.0.0.1 <script> <args></code>. <code>nnodes > 1</code> raises
|
|
128
|
+
<code>NotImplementedError</code> (multi-node rendezvous is a later slice). See the
|
|
129
|
+
<a href="../guides/pytorch.html">PyTorch guide</a>.</p>
|
|
130
|
+
<hr />
|
|
131
|
+
<h2 id="integrationssklearn-fr_sklearn"><code>integrations.sklearn</code> (<code>fr_sklearn</code>)</h2>
|
|
132
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code class="language-python">def sweep(
|
|
133
|
+
script,
|
|
134
|
+
task_params,
|
|
135
|
+
*,
|
|
136
|
+
source=".",
|
|
137
|
+
metric="accuracy_mean",
|
|
138
|
+
maximize=True,
|
|
139
|
+
python="python",
|
|
140
|
+
) -> CommandWorkload: ...
|
|
141
|
+
|
|
142
|
+
def hpo(script, grid, **kwargs) -> CommandWorkload: ...
|
|
143
|
+
</code></pre></div>
|
|
144
|
+
<ul>
|
|
145
|
+
<li><strong><code>sweep</code></strong> — one independent task per params dict; sets
|
|
146
|
+
<code>outputs.primary_metric=metric</code> so <code>run.best_trial()</code> needs no arguments.</li>
|
|
147
|
+
<li><strong><code>hpo</code></strong> — Cartesian-grid sugar over <code>sweep</code>
|
|
148
|
+
(<code>{"model": ["logreg", "rf"], "C": [0.1, 1]}</code> → 4 trials).</li>
|
|
149
|
+
</ul>
|
|
150
|
+
<p>Distributes across runs, never inside a single <code>.fit()</code>. See the
|
|
151
|
+
<a href="../guides/sklearn.html">scikit-learn guide</a>.</p>
|
|
152
|
+
<hr />
|
|
153
|
+
<h2 id="integrationshuggingface-fr_hf"><code>integrations.huggingface</code> (<code>fr_hf</code>)</h2>
|
|
154
|
+
<div class="codeblock"><button class="copybtn" type="button" aria-label="Copy code to clipboard">Copy</button><pre><code class="language-python">def trainer(script, *, source=".", nproc_per_node=1, script_args="") -> CommandWorkload: ...
|
|
155
|
+
|
|
156
|
+
def latest_checkpoint(output_dir) -> str | None: ...
|
|
157
|
+
|
|
158
|
+
def flashruntime_callback(): ... # returns a transformers TrainerCallback
|
|
159
|
+
</code></pre></div>
|
|
160
|
+
<ul>
|
|
161
|
+
<li><strong><code>trainer</code></strong> — a thin wrapper over <code>pytorch.ddp()</code>; launching an HF Trainer
|
|
162
|
+
job is just the PyTorch path (Trainer wraps DDP/FSDP internally under
|
|
163
|
+
<code>torchrun</code>).</li>
|
|
164
|
+
<li><strong><code>latest_checkpoint</code></strong> — newest <code>checkpoint-*</code> dir with a <strong>valid</strong> manifest
|
|
165
|
+
(or <code>None</code>); pass straight to <code>trainer.train(resume_from_checkpoint=...)</code>.</li>
|
|
166
|
+
<li><strong><code>flashruntime_callback</code></strong> — a <code>TrainerCallback</code> whose <code>on_save</code> commits a
|
|
167
|
+
verified manifest and whose <code>on_log</code> relays metrics through
|
|
168
|
+
<code>flashruntime.torch.log_metrics</code>. The <code>transformers</code> import is paid inside
|
|
169
|
+
this factory, in your process.</li>
|
|
170
|
+
</ul>
|
|
171
|
+
<p>See the <a href="../guides/huggingface.html">Hugging Face guide</a>.</p>
|
|
172
|
+
<hr />
|
|
173
|
+
<h2 id="the-extensibility-pattern">The extensibility pattern</h2>
|
|
174
|
+
<p>Every adapter returns a <code>CommandWorkload</code> and reuses the same
|
|
175
|
+
launch/collect/recover machinery. To teach FlashRuntime a new framework, write a
|
|
176
|
+
function under <code>flashruntime/integrations/</code> that returns a <code>CommandWorkload</code>
|
|
177
|
+
describing <em>what to run</em> (and, if the framework has hooks, maps them onto
|
|
178
|
+
<code>write_manifest</code> / <code>log_metrics</code>). No core change is required — that is the
|
|
179
|
+
four-axis payoff. The <a href="sdk.html">SDK reference</a> documents the <code>CommandWorkload</code>
|
|
180
|
+
shape you build.</p></main>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<script>
|
|
184
|
+
// ---- client-side search: fetch the builder's index, filter as you type -----
|
|
185
|
+
// (<=60 lines, vanilla JS, no external anything — the index is a sibling file.)
|
|
186
|
+
let INDEX = [];
|
|
187
|
+
// Path from THIS page back to the site root. The index stores root-relative
|
|
188
|
+
// URLs (e.g. "tutorials/deep.html"); we fetch it and build result links
|
|
189
|
+
// against ROOT so a page in a subdir resolves them too (see build_docs.py).
|
|
190
|
+
const ROOT = "../";
|
|
191
|
+
const q = document.getElementById("q");
|
|
192
|
+
const results = document.getElementById("results");
|
|
193
|
+
const esc = (s) => String(s).replace(/[&<>"]/g, (c) =>
|
|
194
|
+
({ "&": "&", "<": "<", ">": ">", '"': """ }[c]));
|
|
195
|
+
fetch(ROOT + "search-index.json").then((r) => r.json()).then((d) => { INDEX = d; }).catch(() => {});
|
|
196
|
+
|
|
197
|
+
// A short context window around the first match, so a hit shows WHY it matched.
|
|
198
|
+
function snippet(text, needle) {
|
|
199
|
+
const i = text.toLowerCase().indexOf(needle);
|
|
200
|
+
if (i < 0) return "";
|
|
201
|
+
const start = Math.max(0, i - 32);
|
|
202
|
+
return (start > 0 ? "…" : "") + text.slice(start, i + needle.length + 44).trim() + "…";
|
|
203
|
+
}
|
|
204
|
+
function runSearch() {
|
|
205
|
+
const needle = q.value.trim().toLowerCase();
|
|
206
|
+
if (!needle) { results.className = ""; results.innerHTML = ""; return; }
|
|
207
|
+
const hits = INDEX.map((p) => {
|
|
208
|
+
const inTitle = p.title.toLowerCase().includes(needle);
|
|
209
|
+
const inText = p.text.toLowerCase().includes(needle);
|
|
210
|
+
if (!inTitle && !inText) return null;
|
|
211
|
+
return { url: p.url, title: p.title, snip: inText ? snippet(p.text, needle) : "" };
|
|
212
|
+
}).filter(Boolean).slice(0, 20);
|
|
213
|
+
results.className = "open";
|
|
214
|
+
results.innerHTML = hits.length
|
|
215
|
+
? hits.map((h) => '<a href="' + ROOT + h.url + '"><b>' + esc(h.title) + "</b>" +
|
|
216
|
+
(h.snip ? "<span>" + esc(h.snip) + "</span>" : "") + "</a>").join("")
|
|
217
|
+
: '<div class="nohit">no matches</div>';
|
|
218
|
+
}
|
|
219
|
+
q.addEventListener("input", runSearch);
|
|
220
|
+
q.addEventListener("focus", runSearch);
|
|
221
|
+
document.addEventListener("click", (e) => {
|
|
222
|
+
if (!e.target.closest(".search")) { results.className = ""; } // dismiss on outside click
|
|
223
|
+
});
|
|
224
|
+
document.addEventListener("keydown", (e) => { // "/" focuses search, like PyTorch docs
|
|
225
|
+
if (e.key === "/" && document.activeElement !== q) { e.preventDefault(); q.focus(); }
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// ---- copy buttons: read the <pre>'s own text into the clipboard ------------
|
|
229
|
+
document.querySelectorAll(".copybtn").forEach((btn) => {
|
|
230
|
+
btn.addEventListener("click", () => {
|
|
231
|
+
const code = btn.parentElement.querySelector("pre").innerText;
|
|
232
|
+
navigator.clipboard.writeText(code).then(() => {
|
|
233
|
+
const was = btn.textContent; btn.textContent = "Copied";
|
|
234
|
+
setTimeout(() => { btn.textContent = was; }, 1200);
|
|
235
|
+
}).catch(() => {});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
</script>
|
|
239
|
+
</body>
|
|
240
|
+
</html>
|