EcoCompute · Methodology

How EcoCompute measures LLM inference energy

Direct on-device power sampling, not TDP arithmetic. This page is the citable description of the protocol behind every number on quantenergy.tech.

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 · Measurement protocol

QuantityHow it is obtained
GPU powerNVML (nvmlDeviceGetPowerUsage) polled at 10 Hz for the duration of generation; GPU-package power, board-level
WorkloadSingle-stream text generation, 256 output tokens per run, fixed prompt and sampling settings
RepeatsMain dataset (v1.1.0): n = 2 with CV < 2%. RTX 4090 deep dive (July 2026): n = 1 per configuration — one trial whose 10 decode iterations are integrated into a single energy total, so it has no CV. The two layers are drawn differently (see below), never merged into one visual tier
EnergyTime-integral of sampled power over the generation window, normalised to joules per 1M output tokens
BaselineEach model's own FP16 run on the same GPU; ΔE% is relative to that baseline
PrecisionsFP16, NF4, INT8 (FP8 where the hardware supports it) — weight-only quantization
ArchitecturesTuring (T4), Ampere (A800), Ada (RTX 4090 / 4090D), Blackwell (RTX 5090)

2 · 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 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. It is untested; the control is a repeat of one 1.1B INT8 run with the July build (or with the image, on a host that can nest Docker — ours cannot). The decomposition constrains it: 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.

3 · 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 both model size and GPU architecture, it starts to save. Explore your own case on the Your model tab.

4 · 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.

5 · Limitations

6 · How to cite

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