Schema-versioned Roofline analysis, comparison, and plotting for humans and AI agents.
Project description
roofp
Schema-versioned Roofline analysis, comparison, and plotting for humans and AI agents.
roofp accepts JSON configuration, CLI arguments, or structured MCP calls. It generates SVG, PNG, and PDF plots and reports every measured operator against each configured roof. Version 0.2 separates theoretical hardware capability from per-hardware measured utilization and makes dimensional units explicit in the output schema.
Roofline model
For a roof with peak compute P in FLOP/s, bandwidth B in Byte/s, and
arithmetic intensity I in FLOP/Byte:
ridge point = P / B
roof ceiling(I) = min(P, B * I)
utilization = measured performance / roof ceiling(I)
An operator left of the ridge is memory-bound, one right of it is
compute-bound, and a value equal within the documented numerical tolerance is
reported as ridge. A measurement above its configured roof is diagnostic
evidence of mismatched units, precision, FLOP counting, sparsity conventions,
or measurement scope—not a valid utilization winner.
Install and run
The package is published under the distribution name lyroofp. The stable
Python import and command names remain roofp:
python -m pip install lyroofp
roofp --version
Development checkout:
uv sync --locked --all-groups
uv run --no-sync roofp --config examples/sample_config.json
CLI-only example:
uv run --no-sync roofp \
--ideal-compute "1.2 TFLOP/s" \
--ideal-bandwidth "800 GB/s" \
--actual-compute "800 GFLOP/s" \
--actual-bandwidth "500 GB/s" \
--operator GEMM "650 GFLOP/s" "3.25 FLOP/Byte" \
--output roofline.svg
The CLI writes exactly one JSON document to stdout. Human-readable artifact status goes to stderr, so shell tools can safely consume stdout:
uv run --no-sync roofp --config examples/sample_config.json > result.json
Analysis-only mode
--analysis-only skips plotting and atomically writes a JSON artifact.
--silent remains an alias for compatibility:
uv run --no-sync roofp --analysis-only \
--ideal-compute "1.2 TFLOP/s" \
--ideal-bandwidth "800 GB/s" \
--operator GEMM "650 GFLOP/s" "3.25 FLOP/Byte" \
--output analysis.json
When a plot-oriented config selects roofline.svg, adding --analysis-only
uses analysis.json unless the CLI explicitly provides another .json path.
This prevents JSON from being written into an image-named file.
Supported units
Inputs may be normalized numbers, strings, or { "value": ..., "unit": ... }
objects in JSON configuration.
| Quantity | Normalized unit | Examples |
|---|---|---|
| Compute throughput | FLOP/s |
1e12, 1200 GFLOP/s, 1.2 TFLOP/s |
| Bandwidth | Byte/s |
8e11, 800 GB/s, 745 GiB/s |
| Arithmetic intensity | FLOP/Byte |
3.25, 3.25 FLOP/Byte, 650 GFLOP/s/200 GB/s |
Prefixes are case-sensitive: M means mega. Ambiguous lowercase m is
rejected. Uppercase B means bytes; bit-rate forms such as Gb/s and Gbps
are rejected rather than silently interpreted as Byte/s. Bare FLOP is an
operation count, not throughput, and is rejected; common throughput spellings
such as GFLOPS remain supported.
JSON configuration
See the complete sample configuration.
{
"title": "Example Roofline",
"output": "roofline.svg",
"plot": {
"width": 1280,
"height": 720,
"show_bound_regions": true
},
"ideal": {
"label": "FP32 theoretical roof",
"compute": "1.2 TFLOP/s",
"bandwidth": "800 GB/s",
"precision": "FP32",
"compute_kind": "theoretical",
"bandwidth_level": "dram",
"bandwidth_kind": "theoretical",
"fma_flop_count": 2,
"sparsity": "dense"
},
"actual": {
"label": "FP32 measured roof",
"compute": "800 GFLOP/s",
"bandwidth": "500 GB/s",
"precision": "FP32",
"compute_kind": "measured",
"bandwidth_level": "dram",
"bandwidth_kind": "measured",
"fma_flop_count": 2,
"sparsity": "dense"
},
"operators": [
{
"name": "GEMM",
"compute": "650 GFLOP/s",
"arithmetic_intensity": "3.25 FLOP/Byte"
}
]
}
The config schema is strict: misspelled or unknown fields fail early. ideal
is required, actual is optional, and every roof must provide compute and
bandwidth together. All numeric quantities must be finite and positive. When
one or more --operator options are supplied, they replace the configured
operator list rather than appending to it.
Analysis schema 2.0
All analysis results include "schema_version": "2.0". Dimensional names are
explicit, including:
peak_compute_flop_per_secondbandwidth_byte_per_secondmeasured_performance_flop_per_secondachieved_bandwidth_byte_per_secondarithmetic_intensity_flop_per_byteroof_ceiling_flop_per_second
Each operator contains an evaluations object with separate ideal, actual,
and additional_N results. An evaluation includes bound, ridge_ratio,
utilization_ratio, remaining_headroom_ratio, and above_roof. Version 0.2
intentionally removes ambiguous 0.1 aliases such as headroom_ratio and
compute_flops.
MCP server
For development, start the locked environment explicitly:
uv run --locked roofp-mcp
For a long-running client integration, sync once and disable startup syncing:
uv sync --locked
uv run --no-sync roofp-mcp
Example client configuration after the one-time sync:
{
"mcpServers": {
"roofp": {
"command": "uv",
"args": [
"run",
"--no-sync",
"--directory",
"/absolute/path/to/roofp",
"roofp-mcp"
]
}
}
}
The server exposes structured inputs and structured outputs—do not JSON-encode lists inside strings.
analyze_performance
Use one roof and measured operators for diagnosis:
{
"roof": {
"label": "FP32 theoretical",
"compute": "1.2 TFLOP/s",
"bandwidth": "800 GB/s",
"precision": "FP32"
},
"operators": [
{
"name": "GEMM",
"compute": "650 GFLOP/s",
"arithmetic_intensity": "650 GFLOP/s/200 GB/s"
}
]
}
generate_roofline
Accepts a required ideal roof, optional actual roof, and optional operators.
Set include_svg: true to include the SVG. It defaults to false so ordinary
agent calls remain compact; SVG calls support at most 64 plotted points.
compare_rooflines
This tool accepts peer roofs and workloads. Theoretical comparison needs only
arithmetic intensity. Put measured performance under the matching roof label
when a per-hardware utilization comparison is actually available:
{
"roofs": [
{
"label": "System A FP32",
"compute": "1.2 TFLOP/s",
"bandwidth": "800 GB/s",
"precision": "FP32",
"fma_flop_count": 2,
"bandwidth_level": "dram"
},
{
"label": "System B FP32",
"compute": "1.6 TFLOP/s",
"bandwidth": "600 GB/s",
"precision": "FP32",
"fma_flop_count": 2,
"bandwidth_level": "dram"
}
],
"workloads": [
{
"name": "Kernel 1",
"arithmetic_intensity": "2 FLOP/Byte",
"measurements": [
{"roof_label": "System A FP32", "compute": "700 GFLOP/s"},
{"roof_label": "System B FP32", "compute": "850 GFLOP/s"}
]
}
]
}
best_theoretical_hardware ranks capability. best_valid_utilization_hardware
is emitted only from valid per-hardware measurements. Above-roof measurements
are preserved in excluded_above_roof_measurements but cannot win. Metadata
warnings flag mismatched or partially omitted precision, bandwidth level, FMA
count, and sparsity conventions.
AI agent Skill
The repository SKILL.md describes the 0.2 MCP workflow. Install a version-pinned copy for Codex:
mkdir -p ~/.codex/skills/roofp
curl --fail --silent --show-error --location --proto '=https' \
--output ~/.codex/skills/roofp/SKILL.md \
https://raw.githubusercontent.com/luoyueyuguang/roofp/v0.2.0/SKILL.md
For another agent, place the same pinned file at that product's documented skill location. Review the downloaded instructions before enabling them. When release checksums are published, verify the file against the checksum in the same tagged release; this README deliberately does not invent a checksum before release publication.
Tests and release checks
uv sync --locked --all-groups
uv run --no-sync python -W error -m unittest discover -s tests -v
uv run --no-sync ruff check .
uv run --no-sync mypy roofp
uv run --no-sync coverage run -m unittest discover -s tests
uv run --no-sync coverage report
uv build
CI covers Python 3.10–3.14, lowest direct dependencies, protocol behavior, wheel-only installation, linting, type checks, coverage, source distribution, and Skill validation.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lyroofp-0.2.1.tar.gz.
File metadata
- Download URL: lyroofp-0.2.1.tar.gz
- Upload date:
- Size: 939.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecd5488221712310d0d1b6322b055518fcba21b037da85df5d2d6c688595b607
|
|
| MD5 |
874cc44cd1e1c21a3847f20f2311fb21
|
|
| BLAKE2b-256 |
c8679eff39abab341f7c57d0ea3fa768ef536ee1874e24353f520cc97d3e5f40
|
File details
Details for the file lyroofp-0.2.1-py3-none-any.whl.
File metadata
- Download URL: lyroofp-0.2.1-py3-none-any.whl
- Upload date:
- Size: 23.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a487b2ae8549de228d089bb0b38529a1ef8d1e753615bc79e80e6f19d049bc70
|
|
| MD5 |
7912c4a50ea237791810c905acd9e22f
|
|
| BLAKE2b-256 |
f1693fdf52e8c9a4582362308d17c9f1a31cb80699cafd1b63fef66fa9e573a0
|