Some checks failed
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Successful in 44s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m20s
standards workspaces build + test / aac-rs (pull_request) Successful in 2m39s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m26s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 56s
standards workspaces build + test / map-rs (pull_request) Successful in 56s
standards workspaces build + test / mesh-rs (pull_request) Successful in 53s
standards workspaces build + test / openpay (pull_request) Successful in 3m12s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 54s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 4m33s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m1s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 4s
no-vanity-metrics / WAI public text names no comparison (pull_request) Successful in 4s
no-vanity-metrics / WAI public text names no company or product (pull_request) Successful in 4s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m17s
standards workspaces build + test / jcp-rs (pull_request) Failing after 42s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m58s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m12s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m11s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m17s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m14s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m26s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m52s
The annex reported that the macOS per-process energy counter "accrues in lumps" under sub-millisecond sampling, and left it there. The mechanism is now established: a thread's energy is added to its process's count when the thread leaves its core, so a reader on a running thread sees nothing until its quantum ends. A reader that first leaves its core and checks its own thread's count moved reads 1 ms spans to within a few percent of an independent read, where unchecked it read none of them on an idle host. Say so beside the measured figures, which stand. Co-Authored-By: Claude Opus 5.5 <[email protected]>
222 lines
12 KiB
Markdown
222 lines
12 KiB
Markdown
# Proposed Annex: the provenance and validity of E
|
||
|
||
*Draft submission for filing to [github.com/Green-Software-Foundation/sci](https://github.com/Green-Software-Foundation/sci). Licensed CC-BY-4.0.*
|
||
|
||
*Status: working draft v0.1. Authors: Transaction Science. Target: SCI-for-AI, as an annex to the treatment of E. Companion to [`sci-for-ai-submission.md`](sci-for-ai-submission.md), which maps EOC receipts onto the four-component formula and assumes E is already trustworthy; this annex is about whether it is.*
|
||
|
||
---
|
||
|
||
## a. Summary
|
||
|
||
`SCI = (E × I + M) per R` is well specified in every term but one. `I` has a
|
||
location-based methodology. `M` has a lifecycle methodology. `R` is
|
||
deployment-defined and the specification is explicit that it must be *stated
|
||
and reproducible*. **`E` has no comparable requirement.** A figure may be
|
||
labelled "measured" without saying what measured it, over what span, on which
|
||
silicon, or on whose behalf — and in current practice it frequently is.
|
||
|
||
This annex proposes five requirements (E1–E5) that make an `E` figure
|
||
self-describing, and one refusal: **a figure taken over a span shorter than its
|
||
counter's update period is not a measurement of that span and MUST NOT be
|
||
reported as measured.** All five are machine-checkable, and a reference
|
||
implementation exists.
|
||
|
||
**What this annex does not propose.** No change to `R`. SCI-for-AI already
|
||
supports diverse functional units — tokens for language models, inferences for
|
||
classifiers, FLOPs for training — so non-generative inference, including the
|
||
typed-decision models that emerged in September and October 2026 and emit no
|
||
tokens at all, is already expressible as `R = one inference`. The gap is not in
|
||
the unit of work. It is in the energy.
|
||
|
||
## b. The problem, as evidenced
|
||
|
||
Three independent observations, none of them about a careless implementer:
|
||
|
||
1. **Published work that has a sensor reports only part of the machine.** A
|
||
survey of recent AI-energy measurement work finds the instrumented studies
|
||
are GPU-rail-only — no CPU package, no DRAM, no NIC, no storage, no
|
||
power-supply loss — and that none of them declares its sampling interval,
|
||
the device's update rate, or the integration method actually used.
|
||
2. **"Measured" is being applied to estimators.** A reference implementation in
|
||
this ecosystem stamps `measured` on the output of a lifecycle estimator
|
||
whose own documentation calls it an estimation. The alternative path uses
|
||
hard-coded kWh-per-token constants calibrated from a single figure at ±50%.
|
||
Neither is wrong as an estimate; both are wrong as a measurement.
|
||
3. **Per-call energy is being taken from provider SDKs**, which report a number
|
||
with no stated counter, period or boundary. The reporter cannot tell a
|
||
hardware reading from a model, and neither can the reader.
|
||
|
||
### Why this is not pedantry
|
||
|
||
The error is not symmetric. A figure used in a *budget* or a *ceiling* that
|
||
under-reports admits work the budget cannot cover, silently; one that
|
||
over-reports refuses work that would have fit, visibly. A figure used in a
|
||
*disclosure* that under-reports understates an obligation. In both cases the
|
||
unsafe direction is the one an uncharacterised counter takes.
|
||
|
||
And counters do take it, by large factors. A 588-run study of one widely used
|
||
cumulative-energy counter measured it **under-reporting integrated power by
|
||
95.4% at 0.5 ms sampling**, recovering to 1.6% only at 1 s, and recommended
|
||
against unvalidated use. Three weeks later a separate paper built its entire
|
||
per-token energy decomposition on that same counter, specifically *because*
|
||
power sampling cannot resolve short decode windows. Neither cites the other.
|
||
A third observation, on different hardware, has the same counter class reading
|
||
4–30× the board's actual draw when polled at 100 ms. Three mutually
|
||
inconsistent characterisations of one counter class — which means the validity
|
||
bound is itself sampling-interval-dependent and cannot be assumed.
|
||
|
||
We reproduced the shape on a fourth counter. Burning one thread's CPU and
|
||
sampling the macOS per-process energy counter 60 times per interval, the
|
||
fraction of intervals in which it advanced was **0% at 10 µs and 50 µs, 2% at
|
||
100 µs, 5% at 500 µs, 35% at 1 ms, 63% at 2 ms, 87% at 5 ms, and 100% at
|
||
10 ms**. Below 1 ms it does not lag smoothly — on the intervals where it moved
|
||
at all, the median step was ~20 mJ, two orders above the 1 ms step. It accrues
|
||
in lumps. A sampler reading it every 500 µs would see nothing most of the time
|
||
and a 20 mJ jump occasionally, and would report both as measurements.
|
||
|
||
The lumps are the kernel's bookkeeping, not the hardware's. A thread's energy is
|
||
added to its process's count when the thread leaves its core, so a reader on a
|
||
running thread sees nothing until that thread's scheduling quantum ends, and then
|
||
sees all of it at once. A reader that first leaves its core, and checks that its
|
||
own thread's count moved across that pause, reads the same 1 ms spans to within a
|
||
few percent of an independent read; unchecked, on an idle host, it read none of
|
||
them. The counter is exact; an unchecked read of it is not.
|
||
|
||
## c. Proposed requirements
|
||
|
||
An `E` figure claiming to be **measured** MUST carry:
|
||
|
||
**E1 — Source.** The named counter or instrument: `rapl`, `nvml`, `rocm-smi`,
|
||
`level-zero`, `ioreport`, `proc-rusage`, `tegra-ina`, `qualcomm-qpt`,
|
||
`ascend-smi`, `hl-smi`, `cnmon`, `external-meter`, … Not the word "measured".
|
||
Two figures from different sources are not interchangeable: they have different
|
||
domains, different periods and different attribution.
|
||
|
||
**E2 — Period, and the span rule.** The counter's documented or measured update
|
||
period, and the span the figure covers. **If the span is shorter than the
|
||
period, the figure MUST be reported as modelled, not measured.** A source whose
|
||
period is *undeclared* can never support a measured claim at any span, because
|
||
the direction of its error is unknown. A per-operation figure for work shorter
|
||
than the period is sound only as the mean of many operations over a span longer
|
||
than it.
|
||
|
||
**E3 — Attribution boundary.** Whether the figure counts **one principal's**
|
||
work (a per-process or per-container counter) or **the whole machine** (an SoC
|
||
rail, a package counter, a board shunt). These are different claims, and the
|
||
distinction is independent of how much of the *task* is covered. A machine-wide
|
||
figure attributed to one workload MUST state the condition under which that is
|
||
valid — normally exclusive use — and MUST report the magnitude of its idle
|
||
correction, so a reader can see whether the correction is a rounding error or
|
||
the result.
|
||
|
||
**E4 — Fabric breakdown.** Where the work crosses silicon, `E` SHOULD be
|
||
reported per fabric (`cpu`, `gpu`, `npu`, `dram`, `package`, …) and MUST state
|
||
which fabrics are **not** covered. A total that silently omits a fabric the
|
||
work used is an understatement, and on accelerated inference the omitted
|
||
fabric is usually the dominant one.
|
||
|
||
**E5 — Why a fabric is uncovered.** Where a fabric is not measured, the reason
|
||
MUST be one of five, because they are not interchangeable:
|
||
|
||
| status | meaning |
|
||
|---|---|
|
||
| `frozen` | counter present, not advancing |
|
||
| `absent` | no such silicon on this host |
|
||
| `needs-privilege` | present, requires privilege the reporter lacks |
|
||
| `no-counter-exists` | present, and exposes **no energy counter at all** |
|
||
| `not-implemented` | a counter exists; this reporter has no reader for it |
|
||
|
||
Only `no-counter-exists` is a property of the hardware. The other four are
|
||
properties of the deployment or the tooling, and they are fixable.
|
||
|
||
This matters beyond accounting hygiene. The EU AI Act's GPAI Code of Practice
|
||
requires providers to document known or estimated energy consumption for
|
||
training *and* inference, while permitting an exemption where the provider
|
||
lacks "critical information from compute or hardware provider". That exemption
|
||
is a claim of `no-counter-exists`. E5 is what distinguishes it from the four
|
||
statuses that do not justify it — and an unprivileged on-die counter, which
|
||
needs no cooperation from the compute provider at all, narrows the set of
|
||
accelerators for which the claim can honestly be made.
|
||
|
||
## d. Worked example
|
||
|
||
A three-question typed decision served by a 421M-parameter decision model on an
|
||
Apple M5 Max, `R = one inference`:
|
||
|
||
```
|
||
E = 1.0413e-4 Wh (104 127 µJ)
|
||
R = 1 decision
|
||
source = { gpu: ioreport, cpu: proc-rusage }
|
||
period = 10 ms both; span = 2.606 s over 200 decisions → measured (E2 met)
|
||
fabrics = gpu 96 591 µJ attribution=machine, idle-corrected by 0.08%
|
||
cpu 7 536 µJ attribution=process, coverage=whole for CPU work
|
||
npu 0 µJ frozen (no ANE Energy aggregate on this part)
|
||
dram — not-implemented (rails exist; this reader omits them)
|
||
```
|
||
|
||
Two things the annex makes visible that a single number hides. First, the figure
|
||
is a **mean over 200 decisions**, because one decision takes 11.85 ms and a
|
||
10 ms-period counter cannot resolve it — under E2 a per-decision counter read
|
||
would have had to be reported as modelled. Second, 93% of the energy is on a
|
||
**machine-attributed** rail, so the figure is this workload's only under
|
||
exclusive use; the idle correction was 0.08%, which is what makes that credible
|
||
here and would not be on a shared host.
|
||
|
||
The same decision class run on the CPU instead costs **0.486–0.555 J** —
|
||
roughly five times more energy — and is entirely **principal-attributed** and
|
||
whole-coverage. Under E3 those are different claims, and a reporter choosing
|
||
the cheaper figure is also choosing the weaker one. Without E3 the two look
|
||
like the same kind of number, and the cheaper one wins every comparison.
|
||
|
||
## e. Conformance
|
||
|
||
All five requirements are machine-checkable, and we have an implementation
|
||
rather than only a proposal:
|
||
|
||
- A metering ladder that tags every figure with its source and refuses to
|
||
upgrade a model's output to a reading.
|
||
- A per-fabric survey that returns E1, E3, E4 and E5 for every
|
||
`(fabric, source)` pair on a host, probing presence so an unread accelerator
|
||
reports `not-implemented` rather than the false claim `absent`.
|
||
- The E2 refusal as a predicate over `(declared period, span)`, with the
|
||
counter characterisation above as its evidence.
|
||
- Measurement harnesses for both the counter characterisation and the
|
||
per-decision figures, so the numbers in §d are reproducible rather than
|
||
quoted.
|
||
|
||
We propose filing this as an annex under the extension URN
|
||
`urn:gsf:sci-ai:ext:energy-provenance:v1`, additive and imposing nothing on
|
||
deployments that report estimates — which remain perfectly conformant, provided
|
||
they say so.
|
||
|
||
## f. References
|
||
|
||
- **ISO/IEC 21031:2024** — Software Carbon Intensity (SCI) specification.
|
||
- **GSF SCI for AI** — ratified 2025; functional units for language models,
|
||
classifiers and training.
|
||
- **GSF, SCI for AI and EU AI Act environmental compliance** — the policy
|
||
framing this annex is intended to support.
|
||
- **EU AI Act GPAI Code of Practice**, Model Documentation Form — energy
|
||
consumption for training and inference; the compute/hardware-provider
|
||
exemption.
|
||
- Dauner et al., *Evaluating the Influence of Measurement Frequency on
|
||
[GPU energy counters]*, ACM SIGENERGY Energy Informatics Review 6(2),
|
||
July 2026 — the 588-run study; 95.4% under-read at 0.5 ms.
|
||
- *Characterization of Request and Token Energy Costs for LLM Inference
|
||
Workloads*, arXiv:2608.28044 — builds on the same counter for the opposite
|
||
reason.
|
||
- **CEN/CLC/TR 18145:2025**, *Green and Sustainable AI* — the European
|
||
guidance this annex is also offered to.
|
||
- **AFNOR SPEC 2314**, *Référentiel général pour l'IA frugale* — prescribes
|
||
estimator tooling for claims of frugality; E1/E2 are what would let such a
|
||
claim be checked.
|
||
- **Blauer Engel DE-UZ 215** — software energy criteria requiring measurement
|
||
on a defined test system; the German UBA's own reporting names energy per
|
||
classification as a KPI.
|
||
- **UNE 0086:2025** — energy, carbon, water and performance of AI systems.
|
||
|
||
---
|
||
|
||
*Working draft. The filing to `github.com/Green-Software-Foundation/sci` will
|
||
carry a JSON-Schema definition for the E-provenance block, the conformance
|
||
predicate for E2, and the reproducible harnesses behind §d.*
|