EcoCompute · Protocol

Protocol v1.1 — the measurement specification

This is the normative layer of the site: what makes two submissions comparable, so that anyone following this page on any card produces numbers that can be checked against what we have measured. It states no measured results of its own — every number lives in the evidence layer; every count on the site is defined in the number glossary. Execution guides: the container, run it yourself; the machine-checkable contract: the schema.

Where the normative text lives. Protocol v1.1 is now maintained as a standalone specification — EcoCompute Protocol v1.1, written in the W3C-Note / IETF-RFC style with explicit MUST / SHOULD / MAY requirements, bound to the machine contract ("a conforming submission MUST pass ecocompute-energy/1.2+ validation"), and carrying the protocol ↔ schema ↔ dataset version table. The document is archived on Zenodo at DOI 10.5281/zenodo.22958675 — that is the citable reference ("EcoCompute Protocol v1.1, DOI: 10.5281/zenodo.22958675") and this page remains the reader's guide — 导读,附示例与贡献流程. Where this page and the document disagree, the document governs. Version correspondence: the normative text is the Zenodo record at DOI 10.5281/zenodo.22958675 (Protocol v1.1) — it is the version of record, and this guide is synced to that version (the document's §8 version table maps protocol ↔ schema ↔ dataset versions; this page will be updated whenever the record moves to v1.2). Source: spec/ in the site repository.
In one paragraph. Energy per configuration (model × precision × GPU) is obtained by sampling GPU package power with NVML at 10 Hz while the model generates 256 tokens per run, repeating the run and integrating power over wall-clock time. Nothing is derived from thermal design power. Values that are not measured — sizes between or beyond our measured anchors, and latency/throughput — are modelled and labelled as interpolated, extrapolated or estimated in the UI and in the API response. Measurements and estimates are never mixed silently.

1 · What the protocol requires · v1.1 normative

2 · Contributing a measurement · the flow

One GPU, one model, about half an hour (first run including downloads: up to an hour — see the time budget). You do not need a GPU of your own: a free Colab T4 is enough.

The gaps that could change what this site says (not just add rows): runtimes — almost everything here is bitsandbytes, llama.cpp has exactly one cell, vLLM/TensorRT-LLM/SGLang have zero; quant formats — Q4_K_M, GPTQ, AWQ, FP8 on Ada: none measured under this protocol; batch size — every point here is batch 1; cards — no 3090, A100, H100, L4, no AMD (native ROCm telemetry is tracked here — leave your card model and ROCm version to help prioritise it); quality — only 13 of 42 seed rows carry a paired perplexity.

What you get: every accepted submission is published in /replications/ credited by your handle, and drawn on every chart it belongs on — including when it contradicts us; a run that breaks the curve is published as prominently as one that confirms it. Accepted points go into the next Zenodo release of the dataset, which carries its own DOI and names its contributors. Submissions are reviewed by a human for schema and plausibility — never for result — so publication is not instant and is not automatic.

3 · What is measured vs modelled

Every result carries a basis field, and the site renders it as a tag next to the number:

Replication is encoded in the marker, not just in the text

measured says a run exists; it does not say how many times it was repeated. Because the site now shows two measurement layers on the same axes, every chart also encodes replication:

The replication count travels with the data: n_trials in build/measured.csv and n on every anchor in curves.json. Single-trial points still enter the fit — discarding real measurements would be worse — but they are visually marked so no one mistakes one observation for a distribution.

How far apart two single trials land

An n = 1 point has no spread of its own, so we re-ran the same configuration on separate rented RTX 4090 instances to get a sense of the between-session scatter the charts do not show:

These are separate sessions on different instances with different library versions (quantization kernels change between bitsandbytes releases), so the scatter mixes hardware, session and software variation — it is an upper bound on run-to-run noise, not a CV. We keep the runs as separate n = 1 anchors rather than pooling them into an n = 2 point: filled markers on this site mean repeated trials of the same configuration with a measured CV < 2%, and these are not that. The NF4 numbers above come from container validation runs and are not in the dataset.

Run-to-run noise vs between-session scatter: they differ by 30–50×

On 2026-08-20 we ran all five INT8 configurations three times each on one instance, which finally separates the two kinds of variation the point above conflates (raw, per-size mean/SD/CV):

Consequence for anyone using or citing energy deltas, ours included: a quantization penalty measured once on one rented instance can be off by a factor of two, and the run-to-run CV does not warn you about it. The leading hypothesis for our own gap is the LLM.int8() kernel path, which changes with the torch build — and until recently no two of our sessions ran the same one: the 2026-07-24 anchors were recorded with torch 2.4.1+cu121 (Python 3.8), the August native path got torch 2.5.1+cu121, and the container image pins torch 2.13.0. So the kernel explanation could not be separated from everything else that differs between two rented instances two months apart.

That control now exists. On 2026-09-30 four July anchor cells (Qwen2-1.5B and Qwen2-7B at NF4 and INT8) were repeated on the identical stack — torch 2.4.1+cu121, transformers 4.46.3, bitsandbytes 0.45.5, accelerate 1.0.1 — on another RTX 4090. Holding the kernel version fixed did not make the drift go away; it redistributed it by size. The two 7B cells returned to within 1.2 points of July (−28.46% → −28.25% NF4, +49.54% → +50.75% INT8), while the two 1.5B cells moved 7.5 and 16.3 points (+15.11% → +22.6% NF4, +180.73% → +197.05% INT8). Read that with the sentence above: this is what a single measurement is worth when nothing about the software changed — about a point at 7B, and up to sixteen points at 1.5B. Two trials 48 minutes apart on one card agreed to 0.1–4.5 points, so the number by which these rows disagree with July is several times their own within-session noise. (Changelog · 2026-09-30; data: rtx4090_anchor_2026-09-30.csv.)

Still untested: whether the same holds on today's image build. The LLM.int8() decomposition constrains the mechanism: INT8 energy rose 1.41–1.58× at unchanged package power, i.e. purely a throughput effect. One caveat on the repeats: the perplexity column is bit-identical across replicates because teacher forcing is deterministic, so the quality axis has CV = 0 by construction and is not independently replicated.

What the shaded band around a fitted curve is

Every estimate carries a 95% band, and the curve chart shades it. It is not a bootstrap over replicates — most anchors are n = 1, so there are no replicates to resample, and a band built from the within-session CV (0.6–3.9%) would be about a tenth as wide as our own sessions disagree. It is built from how unstable the fit is under its own anchors:

What the band does not cover: between-user and between-session variance. Two of our own sessions on the same card, same protocol, different torch build differ by 100–140 points — far outside any band fitted to one of them. Read the band as the precision of the curve, not as a prediction interval for your machine; the only way to close that gap is independent runs.

The fitted curves and the estimator are open: see estimate.js, optimize.js and the build/ scripts in the site repository.

4 · The finding this protocol produced

Weight-only quantization (NF4/INT8) reliably reduces memory footprint, but it does not always reduce energy. On small models the dequantization overhead outweighs the memory-bandwidth savings, so quantization increases energy per token; above a crossover point that depends on the model size, the GPU architecture and the software stack the numbers were measured on, it starts to save — on one unchanged RTX 5090, a newer stack moved the crossing from ≈5B to ≈1.8B (re-test). Explore your own case on the Your model tab.

5 · Reproduce it on your GPU

The measurement code is a container, not a description. The EcoCompute energy MLCube runs the same NVML sampling on your hardware and writes an energy.json with the exact fields these charts read:

git clone https://github.com/hongping-zh/ecocompute-mlcube.git
cd ecocompute-mlcube

pip install mlcube mlcube-docker
mlcube run --mlcube=. --task=energy_estimate --platform=docker

Then drop the resulting energy.json on the Run it yourself tab to overlay your point on the crossover curve — the overlay is encoded in the URL, nothing is uploaded. The container’s output schema, honesty guarantees, scope and how to contribute a run are documented on the container page.

6 · Number glossary · every count on this site, with its denominator

The site quotes several counts — 42, 29, 144, 26/56, 360+ — that answer different questions and must never be read interchangeably. This table is the single normative definition of each; every page that quotes one links here. Denominators verified against the build scripts, not prose.

NumberWhat it countsDenominator / source
26 / 56 Coverage-matrix cells with at least one measurement (quantization method × GPU architecture × model size, vs a same-card FP16 baseline) 56 grid cells total; 26 filled — data/coverage_matrix_2026-09-09.csv (26 rows), generated by build/make_coverage_matrix.py. The only number on the homepage hero.
29 Crossover-curve anchors: distinct (GPU × model × precision) points the fitted curves are calibrated on build/measured.csv — 29 rows: RTX 4090 ×11 · A800 ×6 · RTX 4090D ×4 · RTX 5090 ×4 · T4 ×4
42 Seed measurement sessions in the v1.1.0 seed set (5 GPU models across 4 architecture classes, plus one contributed RTX 3050 Ti card) Zenodo v1.1.0 dataset provenance. Sessions, not configurations — one session yields several configurations. Supplementary sessions (RTX 5090 re-test, RTX 4090 NF4 two-card re-test, llama.cpp) are not counted.
144 Variable-matrix measurement rows including FP16 baselines (batch size / context length / tokens sweeps) build/make_variable_matrix.py output — 144 measurements, 3 of 15 cells with data. /variables/
360+ Measured configurations in the Zenodo v1.1.0 dataset (model × precision × GPU, incl. n=2 repeated trials) 10.5281/zenodo.19647290 metadata. Dataset-scoped, never quoted as "measurements".

Rule of thumb: 56 answers "what could exist", 26 answers "what has a number", 29 answers "what the curves stand on", 42 and 360+ answer "what is archived in the seed dataset", and 144 counts a separate sweep including its baselines.

7 · Limitations

8 · How to cite

Full artifact map, concept vs version DOIs and BibTeX: Artifacts & citation. In short: