jouleclaw-energy: RAPL reads each package's energy-status MSR where powercap lists none #618
Merged
dcharlot
merged 2 commits from 2026-11-05 04:28:34 -05:00
jouleclaw-energy/rapl-msr into main 2026-11-04
jouleclaw-energy: RAPL MSR domains are per die on Intel, per package on AMD; die zones are packages
All checks were successful
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 12s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 23s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 36s
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Successful in 39s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m34s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 1m50s
energy meters on real hardware / sink decode table · per-task energy and the GPU rail on macOS (pull_request) Successful in 2m19s
energy meters on real hardware / sink decode table · RAPL on jetson-hub (NVML surveyed) (pull_request) Successful in 2m54s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 1m18s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m30s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 3m29s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 3m17s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 1m44s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness (pull_request) Successful in 6m32s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 8m42s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m42s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m24s
wai-quantum WebGPU member / member · GPU, Vulkan (thor) (pull_request) Successful in 24m51s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Successful in 16m55s
Linux scopes Intel's RAPL MSRs per die and AMD's and Hygon's per package (arch/x86/events/rapl.c: "AMD/HYGON platforms have a per-PKG package energy counter", "CLX-AP is multi-die and its RAPL MSRs are die-scope"), and the powercap driver names a multi-die Intel package's zones package-<p>-die-<d>, one top-level zone per die. Two consequences, both corrected here: - The MSR fallback read each package on its first CPU, so on a multi-die Intel package it counted one die: an under-count, the unsafe direction at a ceiling. A domain is now (physical_package_id, die_id) on Intel (die 0 where die_id is absent) and the package on AMD and Hygon, each read on its own lowest-numbered CPU and summed. Single-die parts are unchanged. - The name rule accepted only package-<n>, so a multi-die host's die zones were not packages: no powercap package was listed. It now also accepts package-<n>-die-<m>, and nothing looser. tests/rapl_hardware.rs read powercap only, so on a host with no powercap package its oracle called the counters Unreadable while the meter, as root, read them live through the MSRs, and the burn test had no zone to bracket. The oracle now reads the MSRs itself where powercap lists no package, scoped the same way, and brackets the meter's figure with outer and inner MSR reads. On two bare-metal servers with no powercap zone (Xeon E-2278G; two Xeon Silver 4215R sockets), the hardware tests now pass as root (oracle and meter Live; 6.68 J and 22.07 J over a 300 ms burn, inside the oracle's MSR bracket) and unprivileged (both Unavailable, the meter the estimator). Tests: a two-die Intel package is two domains read on their own first CPUs and summed; an AMD package whose CPUs list several die_ids is one domain; a two-die powercap tree sums both die zones and not psys; the name rule's accepts and near misses. Linux: unit and hardware tests pass (rapl,nvml); macOS: unit tests pass, clippy clean in default, ioreport and rapl. Co-Authored-By: Claude Opus 5.5 <[email protected]>
jouleclaw-energy: RAPL reads each package's energy-status MSR where powercap lists none
All checks were successful
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Successful in 43s
energy meters on real hardware / sink decode table · RAPL on jetson-hub (NVML surveyed) (pull_request) Successful in 2m38s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m41s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 7s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 6s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m21s
energy meters on real hardware / sink decode table · per-task energy and the GPU rail on macOS (pull_request) Successful in 2m20s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 9m33s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 1m40s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness (pull_request) Successful in 6m10s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 9m4s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 2m37s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Successful in 17m20s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 2m36s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 8m15s
wai-quantum WebGPU member / member · GPU, Vulkan (thor) (pull_request) Successful in 25m9s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m15s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 1m9s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 5m44s
Some kernels ship without the powercap RAPL driver (Ubuntu without linux-modules-extra, as on some rented bare-metal servers), so /sys/class/powercap lists no package while the counters are there, and the RAPL counter was unavailable on hosts that can measure. Where powercap lists no package, the counter now reads the same counters directly: each package's MSR_PKG_ENERGY_STATUS (0x611, Intel family 6; 0xC001029B, AMD Zen and Hygon) through /dev/cpu/<first cpu of the package>/msr, the 32-bit count converted at the package's own unit (bits 12:8 of the power-unit MSR), so it wraps at 2^32 counts in microjoules and resolves one count (62 uJ at 2^-14 J). A power-unit MSR that reads zero is no counter (KVM guests read zeros). Powercap is still preferred, and the liveness rule is unchanged: every package readable and live, or no figure. On two bare-metal Supermicro servers with no powercap zone, as root: a Xeon E-2278G live, 59.8 J over 2.0 s, 29.9 W; two Xeon Silver 4215R sockets, summed, live, 155.0 J over 2.0 s, 77.5 W. As an unprivileged user (no CAP_SYS_RAWIO) the counter is Unavailable and the meter falls through. Tests: fake device files (a register's bytes at its offset) cover a two-socket host read on each package's first CPU, the 32-bit wrap, AMD's registers, a zero unit, an unknown CPU, a missing device, powercap preferred, and the production probe over MSR packages. Unit tests pass on Linux and macOS; clippy is clean on macOS (default, ioreport, rapl). Co-Authored-By: Claude Opus 5.5 <[email protected]>