diff --git a/.github/workflows/standards-build.yml b/.github/workflows/standards-build.yml index 95d96037a..bcaa95ed4 100644 --- a/.github/workflows/standards-build.yml +++ b/.github/workflows/standards-build.yml @@ -579,4 +579,10 @@ jobs: lint proof/proof-rs -p proof-cascade -p proof-solvers lint eoc/eoc-rs -p eoc-meter lint jouleclaw/jouleclaw-rs -p jouleclaw-energy --features ioreport + # And the DEFAULT build. Linting only the featured one hid a real + # clippy error for as long as it existed: every hardware meter in + # `detect_meter` is behind a `cfg`, so the default build is a + # different program, and a lint pass that never compiles it cannot + # speak for it. + lint jouleclaw/jouleclaw-rs -p jouleclaw-energy lint sandbox/sandbox-rs -p sandbox-meter -p sandbox-proof diff --git a/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/liveness.rs b/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/liveness.rs index 6ee4c1324..b67819732 100644 --- a/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/liveness.rs +++ b/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/liveness.rs @@ -59,13 +59,21 @@ pub enum CounterLiveness { /// intervals, four in every five of those observed, over at least 300 ms, /// while the probing thread burned CPU. Live, - /// Every channel kept advancing, but a GPU counter (NVML's) ran faster - /// than its board can draw power over the probe: past 1.5 times the - /// board's maximum power limit, or past twice the board's own power draw - /// plus 5 W ([`plausible_gpu_counter`]). It is not counting the board's - /// energy, so its figure would not be a reading of the GPU's work. Seen on - /// an RTX 4050 Laptop GPU (driver 595.84), whose counter runs at 4 to 30 - /// times the board's draw while it is polled. + /// Every channel kept advancing, but a GPU counter (NVML's) did not count + /// its board's energy over the probe — in **either** direction, because + /// the bound is two-sided (`plausible_gpu_counter`): + /// + /// - it ran **faster** than the board can draw power: past 1.5 times the + /// board's maximum power limit, or past twice the board's own power draw + /// plus 5 W. Seen on an RTX 4050 Laptop GPU (driver 595.84), whose + /// counter runs at 4 to 30 times the board's draw while it is polled; + /// - or it accrued **far less** than the board's own telemetry says it + /// drew, below a quarter of that draw once 5 W of slack is taken off it. + /// This is the direction that matters at an energy ceiling, since a + /// counter reading low would otherwise be graded as hardware and then + /// spend a budget it is not measuring. + /// + /// Either way its figure would not be a reading of the GPU's work. Implausible, /// Every channel kept advancing and the counter could not be judged, /// because the board's own power telemetry was unusable over the probe: a diff --git a/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/meter.rs b/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/meter.rs index 80dd9024e..00f87b1ff 100644 --- a/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/meter.rs +++ b/jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/meter.rs @@ -262,6 +262,12 @@ impl EnergyMeter for EstimationMeter { /// reads its cumulative-energy counter as a hardware reading only when that is /// live, and otherwise its power-draw integral, graded `ModelBased`. Each of /// those probes also runs once per process, on the first calling thread. +// Every hardware meter below is behind a `cfg`, so in the default build the +// only push left is the estimator's and clippy reads the vector as one that +// should have been a `vec![..]`. With any meter feature on there are several +// pushes and the lint does not fire — which is why CI never saw it: the clippy +// step lints this crate with `--features ioreport` only. +#[allow(clippy::vec_init_then_push)] pub fn detect_meter() -> CompositeMeter { let mut meters: Vec> = Vec::new();