lyroofp 0.2.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.
- lyroofp-0.2.1/LICENSE +21 -0
- lyroofp-0.2.1/MANIFEST.in +6 -0
- lyroofp-0.2.1/PKG-INFO +349 -0
- lyroofp-0.2.1/README.md +321 -0
- lyroofp-0.2.1/README_zh.md +274 -0
- lyroofp-0.2.1/SKILL.md +166 -0
- lyroofp-0.2.1/docs/assets/logo.png +0 -0
- lyroofp-0.2.1/examples/sample_config.json +54 -0
- lyroofp-0.2.1/lyroofp.egg-info/PKG-INFO +349 -0
- lyroofp-0.2.1/lyroofp.egg-info/SOURCES.txt +28 -0
- lyroofp-0.2.1/lyroofp.egg-info/dependency_links.txt +1 -0
- lyroofp-0.2.1/lyroofp.egg-info/entry_points.txt +3 -0
- lyroofp-0.2.1/lyroofp.egg-info/requires.txt +3 -0
- lyroofp-0.2.1/lyroofp.egg-info/top_level.txt +1 -0
- lyroofp-0.2.1/pyproject.toml +72 -0
- lyroofp-0.2.1/roofp/__init__.py +7 -0
- lyroofp-0.2.1/roofp/__main__.py +4 -0
- lyroofp-0.2.1/roofp/cli.py +369 -0
- lyroofp-0.2.1/roofp/mcp_server.py +445 -0
- lyroofp-0.2.1/roofp/model.py +407 -0
- lyroofp-0.2.1/roofp/plot.py +288 -0
- lyroofp-0.2.1/roofp/units.py +256 -0
- lyroofp-0.2.1/setup.cfg +4 -0
- lyroofp-0.2.1/tests/test_cli.py +204 -0
- lyroofp-0.2.1/tests/test_mcp_protocol.py +86 -0
- lyroofp-0.2.1/tests/test_mcp_tools.py +187 -0
- lyroofp-0.2.1/tests/test_model.py +151 -0
- lyroofp-0.2.1/tests/test_packaging.py +50 -0
- lyroofp-0.2.1/tests/test_plot.py +114 -0
- lyroofp-0.2.1/tests/test_units.py +76 -0
lyroofp-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 roofp contributors
|
|
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.
|
lyroofp-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lyroofp
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Schema-versioned Roofline analysis, comparison, and plotting for humans and AI agents.
|
|
5
|
+
Author: luoyueyuguang
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/luoyueyuguang/roofp
|
|
8
|
+
Project-URL: Repository, https://github.com/luoyueyuguang/roofp
|
|
9
|
+
Project-URL: Issues, https://github.com/luoyueyuguang/roofp/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/luoyueyuguang/roofp#readme
|
|
11
|
+
Keywords: roofline,performance,mcp,visualization
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: matplotlib>=3.8
|
|
25
|
+
Requires-Dist: mcp>=1.28.1
|
|
26
|
+
Requires-Dist: numpy>=1.23
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
[English](https://github.com/luoyueyuguang/roofp/blob/main/README.md) · [中文](https://github.com/luoyueyuguang/roofp/blob/main/README_zh.md)
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<img src="https://raw.githubusercontent.com/luoyueyuguang/roofp/main/docs/assets/logo.png" width="220" alt="roofp logo">
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
<h1 align="center">roofp</h1>
|
|
36
|
+
|
|
37
|
+
<p align="center">
|
|
38
|
+
<strong>Schema-versioned Roofline analysis, comparison, and plotting for humans and AI agents.</strong>
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
roofp accepts JSON configuration, CLI arguments, or structured MCP calls. It
|
|
42
|
+
generates SVG, PNG, and PDF plots and reports every measured operator against
|
|
43
|
+
each configured roof. Version 0.2 separates theoretical hardware capability
|
|
44
|
+
from per-hardware measured utilization and makes dimensional units explicit in
|
|
45
|
+
the output schema.
|
|
46
|
+
|
|
47
|
+
## Roofline model
|
|
48
|
+
|
|
49
|
+
For a roof with peak compute `P` in `FLOP/s`, bandwidth `B` in `Byte/s`, and
|
|
50
|
+
arithmetic intensity `I` in `FLOP/Byte`:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
ridge point = P / B
|
|
54
|
+
roof ceiling(I) = min(P, B * I)
|
|
55
|
+
utilization = measured performance / roof ceiling(I)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
An operator left of the ridge is memory-bound, one right of it is
|
|
59
|
+
compute-bound, and a value equal within the documented numerical tolerance is
|
|
60
|
+
reported as `ridge`. A measurement above its configured roof is diagnostic
|
|
61
|
+
evidence of mismatched units, precision, FLOP counting, sparsity conventions,
|
|
62
|
+
or measurement scope—not a valid utilization winner.
|
|
63
|
+
|
|
64
|
+
## Install and run
|
|
65
|
+
|
|
66
|
+
The package is published under the distribution name `lyroofp`. The stable
|
|
67
|
+
Python import and command names remain `roofp`:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python -m pip install lyroofp
|
|
71
|
+
roofp --version
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Development checkout:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv sync --locked --all-groups
|
|
78
|
+
uv run --no-sync roofp --config examples/sample_config.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
CLI-only example:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
uv run --no-sync roofp \
|
|
85
|
+
--ideal-compute "1.2 TFLOP/s" \
|
|
86
|
+
--ideal-bandwidth "800 GB/s" \
|
|
87
|
+
--actual-compute "800 GFLOP/s" \
|
|
88
|
+
--actual-bandwidth "500 GB/s" \
|
|
89
|
+
--operator GEMM "650 GFLOP/s" "3.25 FLOP/Byte" \
|
|
90
|
+
--output roofline.svg
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The CLI writes exactly one JSON document to stdout. Human-readable artifact
|
|
94
|
+
status goes to stderr, so shell tools can safely consume stdout:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
uv run --no-sync roofp --config examples/sample_config.json > result.json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Analysis-only mode
|
|
101
|
+
|
|
102
|
+
`--analysis-only` skips plotting and atomically writes a JSON artifact.
|
|
103
|
+
`--silent` remains an alias for compatibility:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uv run --no-sync roofp --analysis-only \
|
|
107
|
+
--ideal-compute "1.2 TFLOP/s" \
|
|
108
|
+
--ideal-bandwidth "800 GB/s" \
|
|
109
|
+
--operator GEMM "650 GFLOP/s" "3.25 FLOP/Byte" \
|
|
110
|
+
--output analysis.json
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
When a plot-oriented config selects `roofline.svg`, adding `--analysis-only`
|
|
114
|
+
uses `analysis.json` unless the CLI explicitly provides another `.json` path.
|
|
115
|
+
This prevents JSON from being written into an image-named file.
|
|
116
|
+
|
|
117
|
+
## Supported units
|
|
118
|
+
|
|
119
|
+
Inputs may be normalized numbers, strings, or `{ "value": ..., "unit": ... }`
|
|
120
|
+
objects in JSON configuration.
|
|
121
|
+
|
|
122
|
+
| Quantity | Normalized unit | Examples |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| Compute throughput | `FLOP/s` | `1e12`, `1200 GFLOP/s`, `1.2 TFLOP/s` |
|
|
125
|
+
| Bandwidth | `Byte/s` | `8e11`, `800 GB/s`, `745 GiB/s` |
|
|
126
|
+
| Arithmetic intensity | `FLOP/Byte` | `3.25`, `3.25 FLOP/Byte`, `650 GFLOP/s/200 GB/s` |
|
|
127
|
+
|
|
128
|
+
Prefixes are case-sensitive: `M` means mega. Ambiguous lowercase `m` is
|
|
129
|
+
rejected. Uppercase `B` means bytes; bit-rate forms such as `Gb/s` and `Gbps`
|
|
130
|
+
are rejected rather than silently interpreted as Byte/s. Bare `FLOP` is an
|
|
131
|
+
operation count, not throughput, and is rejected; common throughput spellings
|
|
132
|
+
such as `GFLOPS` remain supported.
|
|
133
|
+
|
|
134
|
+
## JSON configuration
|
|
135
|
+
|
|
136
|
+
See the complete [sample configuration](https://github.com/luoyueyuguang/roofp/blob/main/examples/sample_config.json).
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"title": "Example Roofline",
|
|
141
|
+
"output": "roofline.svg",
|
|
142
|
+
"plot": {
|
|
143
|
+
"width": 1280,
|
|
144
|
+
"height": 720,
|
|
145
|
+
"show_bound_regions": true
|
|
146
|
+
},
|
|
147
|
+
"ideal": {
|
|
148
|
+
"label": "FP32 theoretical roof",
|
|
149
|
+
"compute": "1.2 TFLOP/s",
|
|
150
|
+
"bandwidth": "800 GB/s",
|
|
151
|
+
"precision": "FP32",
|
|
152
|
+
"compute_kind": "theoretical",
|
|
153
|
+
"bandwidth_level": "dram",
|
|
154
|
+
"bandwidth_kind": "theoretical",
|
|
155
|
+
"fma_flop_count": 2,
|
|
156
|
+
"sparsity": "dense"
|
|
157
|
+
},
|
|
158
|
+
"actual": {
|
|
159
|
+
"label": "FP32 measured roof",
|
|
160
|
+
"compute": "800 GFLOP/s",
|
|
161
|
+
"bandwidth": "500 GB/s",
|
|
162
|
+
"precision": "FP32",
|
|
163
|
+
"compute_kind": "measured",
|
|
164
|
+
"bandwidth_level": "dram",
|
|
165
|
+
"bandwidth_kind": "measured",
|
|
166
|
+
"fma_flop_count": 2,
|
|
167
|
+
"sparsity": "dense"
|
|
168
|
+
},
|
|
169
|
+
"operators": [
|
|
170
|
+
{
|
|
171
|
+
"name": "GEMM",
|
|
172
|
+
"compute": "650 GFLOP/s",
|
|
173
|
+
"arithmetic_intensity": "3.25 FLOP/Byte"
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The config schema is strict: misspelled or unknown fields fail early. `ideal`
|
|
180
|
+
is required, `actual` is optional, and every roof must provide compute and
|
|
181
|
+
bandwidth together. All numeric quantities must be finite and positive. When
|
|
182
|
+
one or more `--operator` options are supplied, they replace the configured
|
|
183
|
+
operator list rather than appending to it.
|
|
184
|
+
|
|
185
|
+
## Analysis schema 2.0
|
|
186
|
+
|
|
187
|
+
All analysis results include `"schema_version": "2.0"`. Dimensional names are
|
|
188
|
+
explicit, including:
|
|
189
|
+
|
|
190
|
+
- `peak_compute_flop_per_second`
|
|
191
|
+
- `bandwidth_byte_per_second`
|
|
192
|
+
- `measured_performance_flop_per_second`
|
|
193
|
+
- `achieved_bandwidth_byte_per_second`
|
|
194
|
+
- `arithmetic_intensity_flop_per_byte`
|
|
195
|
+
- `roof_ceiling_flop_per_second`
|
|
196
|
+
|
|
197
|
+
Each operator contains an `evaluations` object with separate `ideal`, `actual`,
|
|
198
|
+
and `additional_N` results. An evaluation includes `bound`, `ridge_ratio`,
|
|
199
|
+
`utilization_ratio`, `remaining_headroom_ratio`, and `above_roof`. Version 0.2
|
|
200
|
+
intentionally removes ambiguous 0.1 aliases such as `headroom_ratio` and
|
|
201
|
+
`compute_flops`.
|
|
202
|
+
|
|
203
|
+
## MCP server
|
|
204
|
+
|
|
205
|
+
For development, start the locked environment explicitly:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
uv run --locked roofp-mcp
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
For a long-running client integration, sync once and disable startup syncing:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
uv sync --locked
|
|
215
|
+
uv run --no-sync roofp-mcp
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Example client configuration after the one-time sync:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"mcpServers": {
|
|
223
|
+
"roofp": {
|
|
224
|
+
"command": "uv",
|
|
225
|
+
"args": [
|
|
226
|
+
"run",
|
|
227
|
+
"--no-sync",
|
|
228
|
+
"--directory",
|
|
229
|
+
"/absolute/path/to/roofp",
|
|
230
|
+
"roofp-mcp"
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The server exposes structured inputs and structured outputs—do not JSON-encode
|
|
238
|
+
lists inside strings.
|
|
239
|
+
|
|
240
|
+
### `analyze_performance`
|
|
241
|
+
|
|
242
|
+
Use one roof and measured operators for diagnosis:
|
|
243
|
+
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"roof": {
|
|
247
|
+
"label": "FP32 theoretical",
|
|
248
|
+
"compute": "1.2 TFLOP/s",
|
|
249
|
+
"bandwidth": "800 GB/s",
|
|
250
|
+
"precision": "FP32"
|
|
251
|
+
},
|
|
252
|
+
"operators": [
|
|
253
|
+
{
|
|
254
|
+
"name": "GEMM",
|
|
255
|
+
"compute": "650 GFLOP/s",
|
|
256
|
+
"arithmetic_intensity": "650 GFLOP/s/200 GB/s"
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### `generate_roofline`
|
|
263
|
+
|
|
264
|
+
Accepts a required `ideal` roof, optional `actual` roof, and optional operators.
|
|
265
|
+
Set `include_svg: true` to include the SVG. It defaults to false so ordinary
|
|
266
|
+
agent calls remain compact; SVG calls support at most 64 plotted points.
|
|
267
|
+
|
|
268
|
+
### `compare_rooflines`
|
|
269
|
+
|
|
270
|
+
This tool accepts peer `roofs` and workloads. Theoretical comparison needs only
|
|
271
|
+
arithmetic intensity. Put measured performance under the matching roof label
|
|
272
|
+
when a per-hardware utilization comparison is actually available:
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"roofs": [
|
|
277
|
+
{
|
|
278
|
+
"label": "System A FP32",
|
|
279
|
+
"compute": "1.2 TFLOP/s",
|
|
280
|
+
"bandwidth": "800 GB/s",
|
|
281
|
+
"precision": "FP32",
|
|
282
|
+
"fma_flop_count": 2,
|
|
283
|
+
"bandwidth_level": "dram"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"label": "System B FP32",
|
|
287
|
+
"compute": "1.6 TFLOP/s",
|
|
288
|
+
"bandwidth": "600 GB/s",
|
|
289
|
+
"precision": "FP32",
|
|
290
|
+
"fma_flop_count": 2,
|
|
291
|
+
"bandwidth_level": "dram"
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
"workloads": [
|
|
295
|
+
{
|
|
296
|
+
"name": "Kernel 1",
|
|
297
|
+
"arithmetic_intensity": "2 FLOP/Byte",
|
|
298
|
+
"measurements": [
|
|
299
|
+
{"roof_label": "System A FP32", "compute": "700 GFLOP/s"},
|
|
300
|
+
{"roof_label": "System B FP32", "compute": "850 GFLOP/s"}
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
`best_theoretical_hardware` ranks capability. `best_valid_utilization_hardware`
|
|
308
|
+
is emitted only from valid per-hardware measurements. Above-roof measurements
|
|
309
|
+
are preserved in `excluded_above_roof_measurements` but cannot win. Metadata
|
|
310
|
+
warnings flag mismatched or partially omitted precision, bandwidth level, FMA
|
|
311
|
+
count, and sparsity conventions.
|
|
312
|
+
|
|
313
|
+
## AI agent Skill
|
|
314
|
+
|
|
315
|
+
The repository [SKILL.md](https://github.com/luoyueyuguang/roofp/blob/main/SKILL.md)
|
|
316
|
+
describes the 0.2 MCP workflow. Install a version-pinned copy for Codex:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
mkdir -p ~/.codex/skills/roofp
|
|
320
|
+
curl --fail --silent --show-error --location --proto '=https' \
|
|
321
|
+
--output ~/.codex/skills/roofp/SKILL.md \
|
|
322
|
+
https://raw.githubusercontent.com/luoyueyuguang/roofp/v0.2.0/SKILL.md
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
For another agent, place the same pinned file at that product's documented
|
|
326
|
+
skill location. Review the downloaded instructions before enabling them. When
|
|
327
|
+
release checksums are published, verify the file against the checksum in the
|
|
328
|
+
same tagged release; this README deliberately does not invent a checksum before
|
|
329
|
+
release publication.
|
|
330
|
+
|
|
331
|
+
## Tests and release checks
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
uv sync --locked --all-groups
|
|
335
|
+
uv run --no-sync python -W error -m unittest discover -s tests -v
|
|
336
|
+
uv run --no-sync ruff check .
|
|
337
|
+
uv run --no-sync mypy roofp
|
|
338
|
+
uv run --no-sync coverage run -m unittest discover -s tests
|
|
339
|
+
uv run --no-sync coverage report
|
|
340
|
+
uv build
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
CI covers Python 3.10–3.14, lowest direct dependencies, protocol behavior,
|
|
344
|
+
wheel-only installation, linting, type checks, coverage, source distribution,
|
|
345
|
+
and Skill validation.
|
|
346
|
+
|
|
347
|
+
## License
|
|
348
|
+
|
|
349
|
+
MIT. See [LICENSE](https://github.com/luoyueyuguang/roofp/blob/main/LICENSE).
|
lyroofp-0.2.1/README.md
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
[English](https://github.com/luoyueyuguang/roofp/blob/main/README.md) · [中文](https://github.com/luoyueyuguang/roofp/blob/main/README_zh.md)
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/luoyueyuguang/roofp/main/docs/assets/logo.png" width="220" alt="roofp logo">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">roofp</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<strong>Schema-versioned Roofline analysis, comparison, and plotting for humans and AI agents.</strong>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
roofp accepts JSON configuration, CLI arguments, or structured MCP calls. It
|
|
14
|
+
generates SVG, PNG, and PDF plots and reports every measured operator against
|
|
15
|
+
each configured roof. Version 0.2 separates theoretical hardware capability
|
|
16
|
+
from per-hardware measured utilization and makes dimensional units explicit in
|
|
17
|
+
the output schema.
|
|
18
|
+
|
|
19
|
+
## Roofline model
|
|
20
|
+
|
|
21
|
+
For a roof with peak compute `P` in `FLOP/s`, bandwidth `B` in `Byte/s`, and
|
|
22
|
+
arithmetic intensity `I` in `FLOP/Byte`:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
ridge point = P / B
|
|
26
|
+
roof ceiling(I) = min(P, B * I)
|
|
27
|
+
utilization = measured performance / roof ceiling(I)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
An operator left of the ridge is memory-bound, one right of it is
|
|
31
|
+
compute-bound, and a value equal within the documented numerical tolerance is
|
|
32
|
+
reported as `ridge`. A measurement above its configured roof is diagnostic
|
|
33
|
+
evidence of mismatched units, precision, FLOP counting, sparsity conventions,
|
|
34
|
+
or measurement scope—not a valid utilization winner.
|
|
35
|
+
|
|
36
|
+
## Install and run
|
|
37
|
+
|
|
38
|
+
The package is published under the distribution name `lyroofp`. The stable
|
|
39
|
+
Python import and command names remain `roofp`:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python -m pip install lyroofp
|
|
43
|
+
roofp --version
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Development checkout:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv sync --locked --all-groups
|
|
50
|
+
uv run --no-sync roofp --config examples/sample_config.json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
CLI-only example:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv run --no-sync roofp \
|
|
57
|
+
--ideal-compute "1.2 TFLOP/s" \
|
|
58
|
+
--ideal-bandwidth "800 GB/s" \
|
|
59
|
+
--actual-compute "800 GFLOP/s" \
|
|
60
|
+
--actual-bandwidth "500 GB/s" \
|
|
61
|
+
--operator GEMM "650 GFLOP/s" "3.25 FLOP/Byte" \
|
|
62
|
+
--output roofline.svg
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The CLI writes exactly one JSON document to stdout. Human-readable artifact
|
|
66
|
+
status goes to stderr, so shell tools can safely consume stdout:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uv run --no-sync roofp --config examples/sample_config.json > result.json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Analysis-only mode
|
|
73
|
+
|
|
74
|
+
`--analysis-only` skips plotting and atomically writes a JSON artifact.
|
|
75
|
+
`--silent` remains an alias for compatibility:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv run --no-sync roofp --analysis-only \
|
|
79
|
+
--ideal-compute "1.2 TFLOP/s" \
|
|
80
|
+
--ideal-bandwidth "800 GB/s" \
|
|
81
|
+
--operator GEMM "650 GFLOP/s" "3.25 FLOP/Byte" \
|
|
82
|
+
--output analysis.json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
When a plot-oriented config selects `roofline.svg`, adding `--analysis-only`
|
|
86
|
+
uses `analysis.json` unless the CLI explicitly provides another `.json` path.
|
|
87
|
+
This prevents JSON from being written into an image-named file.
|
|
88
|
+
|
|
89
|
+
## Supported units
|
|
90
|
+
|
|
91
|
+
Inputs may be normalized numbers, strings, or `{ "value": ..., "unit": ... }`
|
|
92
|
+
objects in JSON configuration.
|
|
93
|
+
|
|
94
|
+
| Quantity | Normalized unit | Examples |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| Compute throughput | `FLOP/s` | `1e12`, `1200 GFLOP/s`, `1.2 TFLOP/s` |
|
|
97
|
+
| Bandwidth | `Byte/s` | `8e11`, `800 GB/s`, `745 GiB/s` |
|
|
98
|
+
| Arithmetic intensity | `FLOP/Byte` | `3.25`, `3.25 FLOP/Byte`, `650 GFLOP/s/200 GB/s` |
|
|
99
|
+
|
|
100
|
+
Prefixes are case-sensitive: `M` means mega. Ambiguous lowercase `m` is
|
|
101
|
+
rejected. Uppercase `B` means bytes; bit-rate forms such as `Gb/s` and `Gbps`
|
|
102
|
+
are rejected rather than silently interpreted as Byte/s. Bare `FLOP` is an
|
|
103
|
+
operation count, not throughput, and is rejected; common throughput spellings
|
|
104
|
+
such as `GFLOPS` remain supported.
|
|
105
|
+
|
|
106
|
+
## JSON configuration
|
|
107
|
+
|
|
108
|
+
See the complete [sample configuration](https://github.com/luoyueyuguang/roofp/blob/main/examples/sample_config.json).
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"title": "Example Roofline",
|
|
113
|
+
"output": "roofline.svg",
|
|
114
|
+
"plot": {
|
|
115
|
+
"width": 1280,
|
|
116
|
+
"height": 720,
|
|
117
|
+
"show_bound_regions": true
|
|
118
|
+
},
|
|
119
|
+
"ideal": {
|
|
120
|
+
"label": "FP32 theoretical roof",
|
|
121
|
+
"compute": "1.2 TFLOP/s",
|
|
122
|
+
"bandwidth": "800 GB/s",
|
|
123
|
+
"precision": "FP32",
|
|
124
|
+
"compute_kind": "theoretical",
|
|
125
|
+
"bandwidth_level": "dram",
|
|
126
|
+
"bandwidth_kind": "theoretical",
|
|
127
|
+
"fma_flop_count": 2,
|
|
128
|
+
"sparsity": "dense"
|
|
129
|
+
},
|
|
130
|
+
"actual": {
|
|
131
|
+
"label": "FP32 measured roof",
|
|
132
|
+
"compute": "800 GFLOP/s",
|
|
133
|
+
"bandwidth": "500 GB/s",
|
|
134
|
+
"precision": "FP32",
|
|
135
|
+
"compute_kind": "measured",
|
|
136
|
+
"bandwidth_level": "dram",
|
|
137
|
+
"bandwidth_kind": "measured",
|
|
138
|
+
"fma_flop_count": 2,
|
|
139
|
+
"sparsity": "dense"
|
|
140
|
+
},
|
|
141
|
+
"operators": [
|
|
142
|
+
{
|
|
143
|
+
"name": "GEMM",
|
|
144
|
+
"compute": "650 GFLOP/s",
|
|
145
|
+
"arithmetic_intensity": "3.25 FLOP/Byte"
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The config schema is strict: misspelled or unknown fields fail early. `ideal`
|
|
152
|
+
is required, `actual` is optional, and every roof must provide compute and
|
|
153
|
+
bandwidth together. All numeric quantities must be finite and positive. When
|
|
154
|
+
one or more `--operator` options are supplied, they replace the configured
|
|
155
|
+
operator list rather than appending to it.
|
|
156
|
+
|
|
157
|
+
## Analysis schema 2.0
|
|
158
|
+
|
|
159
|
+
All analysis results include `"schema_version": "2.0"`. Dimensional names are
|
|
160
|
+
explicit, including:
|
|
161
|
+
|
|
162
|
+
- `peak_compute_flop_per_second`
|
|
163
|
+
- `bandwidth_byte_per_second`
|
|
164
|
+
- `measured_performance_flop_per_second`
|
|
165
|
+
- `achieved_bandwidth_byte_per_second`
|
|
166
|
+
- `arithmetic_intensity_flop_per_byte`
|
|
167
|
+
- `roof_ceiling_flop_per_second`
|
|
168
|
+
|
|
169
|
+
Each operator contains an `evaluations` object with separate `ideal`, `actual`,
|
|
170
|
+
and `additional_N` results. An evaluation includes `bound`, `ridge_ratio`,
|
|
171
|
+
`utilization_ratio`, `remaining_headroom_ratio`, and `above_roof`. Version 0.2
|
|
172
|
+
intentionally removes ambiguous 0.1 aliases such as `headroom_ratio` and
|
|
173
|
+
`compute_flops`.
|
|
174
|
+
|
|
175
|
+
## MCP server
|
|
176
|
+
|
|
177
|
+
For development, start the locked environment explicitly:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
uv run --locked roofp-mcp
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For a long-running client integration, sync once and disable startup syncing:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
uv sync --locked
|
|
187
|
+
uv run --no-sync roofp-mcp
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Example client configuration after the one-time sync:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"mcpServers": {
|
|
195
|
+
"roofp": {
|
|
196
|
+
"command": "uv",
|
|
197
|
+
"args": [
|
|
198
|
+
"run",
|
|
199
|
+
"--no-sync",
|
|
200
|
+
"--directory",
|
|
201
|
+
"/absolute/path/to/roofp",
|
|
202
|
+
"roofp-mcp"
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The server exposes structured inputs and structured outputs—do not JSON-encode
|
|
210
|
+
lists inside strings.
|
|
211
|
+
|
|
212
|
+
### `analyze_performance`
|
|
213
|
+
|
|
214
|
+
Use one roof and measured operators for diagnosis:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"roof": {
|
|
219
|
+
"label": "FP32 theoretical",
|
|
220
|
+
"compute": "1.2 TFLOP/s",
|
|
221
|
+
"bandwidth": "800 GB/s",
|
|
222
|
+
"precision": "FP32"
|
|
223
|
+
},
|
|
224
|
+
"operators": [
|
|
225
|
+
{
|
|
226
|
+
"name": "GEMM",
|
|
227
|
+
"compute": "650 GFLOP/s",
|
|
228
|
+
"arithmetic_intensity": "650 GFLOP/s/200 GB/s"
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `generate_roofline`
|
|
235
|
+
|
|
236
|
+
Accepts a required `ideal` roof, optional `actual` roof, and optional operators.
|
|
237
|
+
Set `include_svg: true` to include the SVG. It defaults to false so ordinary
|
|
238
|
+
agent calls remain compact; SVG calls support at most 64 plotted points.
|
|
239
|
+
|
|
240
|
+
### `compare_rooflines`
|
|
241
|
+
|
|
242
|
+
This tool accepts peer `roofs` and workloads. Theoretical comparison needs only
|
|
243
|
+
arithmetic intensity. Put measured performance under the matching roof label
|
|
244
|
+
when a per-hardware utilization comparison is actually available:
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"roofs": [
|
|
249
|
+
{
|
|
250
|
+
"label": "System A FP32",
|
|
251
|
+
"compute": "1.2 TFLOP/s",
|
|
252
|
+
"bandwidth": "800 GB/s",
|
|
253
|
+
"precision": "FP32",
|
|
254
|
+
"fma_flop_count": 2,
|
|
255
|
+
"bandwidth_level": "dram"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"label": "System B FP32",
|
|
259
|
+
"compute": "1.6 TFLOP/s",
|
|
260
|
+
"bandwidth": "600 GB/s",
|
|
261
|
+
"precision": "FP32",
|
|
262
|
+
"fma_flop_count": 2,
|
|
263
|
+
"bandwidth_level": "dram"
|
|
264
|
+
}
|
|
265
|
+
],
|
|
266
|
+
"workloads": [
|
|
267
|
+
{
|
|
268
|
+
"name": "Kernel 1",
|
|
269
|
+
"arithmetic_intensity": "2 FLOP/Byte",
|
|
270
|
+
"measurements": [
|
|
271
|
+
{"roof_label": "System A FP32", "compute": "700 GFLOP/s"},
|
|
272
|
+
{"roof_label": "System B FP32", "compute": "850 GFLOP/s"}
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
`best_theoretical_hardware` ranks capability. `best_valid_utilization_hardware`
|
|
280
|
+
is emitted only from valid per-hardware measurements. Above-roof measurements
|
|
281
|
+
are preserved in `excluded_above_roof_measurements` but cannot win. Metadata
|
|
282
|
+
warnings flag mismatched or partially omitted precision, bandwidth level, FMA
|
|
283
|
+
count, and sparsity conventions.
|
|
284
|
+
|
|
285
|
+
## AI agent Skill
|
|
286
|
+
|
|
287
|
+
The repository [SKILL.md](https://github.com/luoyueyuguang/roofp/blob/main/SKILL.md)
|
|
288
|
+
describes the 0.2 MCP workflow. Install a version-pinned copy for Codex:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
mkdir -p ~/.codex/skills/roofp
|
|
292
|
+
curl --fail --silent --show-error --location --proto '=https' \
|
|
293
|
+
--output ~/.codex/skills/roofp/SKILL.md \
|
|
294
|
+
https://raw.githubusercontent.com/luoyueyuguang/roofp/v0.2.0/SKILL.md
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
For another agent, place the same pinned file at that product's documented
|
|
298
|
+
skill location. Review the downloaded instructions before enabling them. When
|
|
299
|
+
release checksums are published, verify the file against the checksum in the
|
|
300
|
+
same tagged release; this README deliberately does not invent a checksum before
|
|
301
|
+
release publication.
|
|
302
|
+
|
|
303
|
+
## Tests and release checks
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
uv sync --locked --all-groups
|
|
307
|
+
uv run --no-sync python -W error -m unittest discover -s tests -v
|
|
308
|
+
uv run --no-sync ruff check .
|
|
309
|
+
uv run --no-sync mypy roofp
|
|
310
|
+
uv run --no-sync coverage run -m unittest discover -s tests
|
|
311
|
+
uv run --no-sync coverage report
|
|
312
|
+
uv build
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
CI covers Python 3.10–3.14, lowest direct dependencies, protocol behavior,
|
|
316
|
+
wheel-only installation, linting, type checks, coverage, source distribution,
|
|
317
|
+
and Skill validation.
|
|
318
|
+
|
|
319
|
+
## License
|
|
320
|
+
|
|
321
|
+
MIT. See [LICENSE](https://github.com/luoyueyuguang/roofp/blob/main/LICENSE).
|