Skip to content

fix: skip uncorrectable RAPL counter wraps - #1321

Open
davidberenstein1957 wants to merge 1 commit into
masterfrom
fix/rapl-wraparound-negative-energy
Open

fix: skip uncorrectable RAPL counter wraps#1321
davidberenstein1957 wants to merge 1 commit into
masterfrom
fix/rapl-wraparound-negative-energy

Conversation

@davidberenstein1957

Copy link
Copy Markdown
Collaborator

Closes #1309

What changed

RAPLFile.delta() now re-checks the wrap correction: if the corrected reading is still below the previous one, the sample is dropped (zero energy delta, zero power) with a warning, instead of emitting a negative energy delta.

Why

max_energy_range_uj is set to 0 whenever it cannot be read (codecarbon/core/rapl.py:45). The comment claims wrap detection is then disabled, but only the correction was disabled — the wrap branch still ran and produced energy_delta = energy - last_energy, a large negative value (up to -1.19e-3 kWh for a 2^32 uJ package domain). That flows unchecked into _total_energy / _total_cpu_energy, and the abs() in Power.from_energies_and_delay masks it in the power column.

The same guard also covers the other sources of a backwards counter: driver resets, suspend/resume, and the _get_value() transient-error fallback that returns 0. It mirrors what codecarbon/core/windows_emi.py:566-574 already does for EMI.

Dropping a sample loses at most one interval of genuine energy — strictly better than subtracting an hour's worth. Systems where max_energy_range_uj is readable are unaffected.

Verification

tests/test_rapl_permissions.py:

  • test_rapl_wraparound_without_max_skips_sample — fails on master (energy_delta.kWh is about -1.11e-3), passes here.
  • test_rapl_wraparound_with_max_is_corrected — pins the existing wrap correction against regression.

uv run pytest tests/test_rapl_permissions.py -q → 2 passed, 2 skipped (the pre-existing Linux-only cases). black --check clean; ruff reports only pre-existing findings in the touched files.

Merge order

This should land before the rapl_include_dram change: DRAM domains have smaller max ranges and wrap far more often, which makes this defect fire much more frequently.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.62%. Comparing base (3ec31a0) to head (f59ac22).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1321      +/-   ##
==========================================
+ Coverage   91.43%   91.62%   +0.18%     
==========================================
  Files          49       49              
  Lines        5057     5072      +15     
==========================================
+ Hits         4624     4647      +23     
+ Misses        433      425       -8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@davidberenstein1957
davidberenstein1957 marked this pull request as ready for review August 12, 2026 19:14
@davidberenstein1957
davidberenstein1957 requested a review from a team as a code owner August 12, 2026 19:14
@davidberenstein1957
davidberenstein1957 force-pushed the fix/rapl-wraparound-negative-energy branch 2 times, most recently from 4e88977 to d4a9959 Compare August 19, 2026 14:29
When `max_energy_range_uj` is unreadable, `max_energy_reading` is 0, so the
wrap-around branch still ran but corrected nothing, emitting a large negative
energy delta straight into the CPU and total energy. Drop the sample instead,
matching the EMI backend's behaviour. The same guard also covers driver resets
and the transient read-error fallback.

A failed read previously returned `Energy(0)`, which looked like a wrap-around
and, with a readable `max_energy_range_uj`, injected a spurious positive delta
of up to one counter range. `_get_value` now returns None, and the sample is
skipped and re-baselined. The uncorrectable-wrap warning is emitted once per
file instead of on every measurement cycle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@davidberenstein1957
davidberenstein1957 force-pushed the fix/rapl-wraparound-negative-energy branch from d4a9959 to f59ac22 Compare August 20, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RAPL counter wrap yields negative energy when max_energy_range_uj is unreadable

1 participant