jouleclaw-energy: another process's GPU client going back is not this pid's problem #278

Merged
dcharlot merged 1 commit from fix/process-gpu-oracle-pid-time into main 2026-10-17 04:01:43 -04:00
Owner

a_gpu_span_is_a_sole_users_rail_or_an_exact_zero_or_no_figure fails intermittently on the macOS energy job with

no client's time went back in the oracle's window

Why

oracle_times walks every client in the second reading and gives up the whole result if any one of their counters went back:

let d = ns.checked_sub(a.clients.get(id).map_or(0, |c| c.1))?;
all += d;
if *p == pid { me += d; }

It has to, because its all must be exact to compare against a share. But two of its three callers want only one pid's own time — both read let (child_ns, _, _) = ... and discard all — so a client of a wholly unrelated process being destroyed, or its id reused, takes away a figure that never depended on it. The GPU is shared with whatever else the host runs, which is exactly when that happens.

The change

oracle_pid_time totals the named pid's clients and no others, and those two callers use it. The strict reader stays where all is actually used (one site).

The test is deterministic rather than waiting for a host client to vanish: it builds the two readings, with this pid's client advancing 5 ms while another process's goes back, and pins that oracle_times gives up where oracle_pid_time does not. It also pins the two cases that must not become lenient — this pid's own client going back is still no figure, and a pid with no clients is an exact zero rather than unavailable.

Verified on the GPU host

target:   2 tests   (with --features ioreport; without it: 0 tests, and cargo still exits 0)
baseline: rc=0   passed=1 failed=0
mutated:  rc=101 passed=0 failed=1   <- oracle_pid_time put back to totalling every client

So the new test discriminates rather than decorates. CI reaches it the same way: cargo test -p jouleclaw-energy --features ioreport, which the workflow already notes is double-gated on feature and platform.

🤖 Generated with Claude Code

`a_gpu_span_is_a_sole_users_rail_or_an_exact_zero_or_no_figure` fails intermittently on the macOS energy job with ``` no client's time went back in the oracle's window ``` ### Why `oracle_times` walks **every** client in the second reading and gives up the whole result if any one of their counters went back: ```rust let d = ns.checked_sub(a.clients.get(id).map_or(0, |c| c.1))?; all += d; if *p == pid { me += d; } ``` It has to, because its `all` must be exact to compare against a share. But **two of its three callers want only one pid's own time** — both read `let (child_ns, _, _) = ...` and discard `all` — so a client of a wholly unrelated process being destroyed, or its id reused, takes away a figure that never depended on it. The GPU is shared with whatever else the host runs, which is exactly when that happens. ### The change `oracle_pid_time` totals the named pid's clients and no others, and those two callers use it. The strict reader stays where `all` is actually used (one site). The test is **deterministic** rather than waiting for a host client to vanish: it builds the two readings, with this pid's client advancing 5 ms while another process's goes back, and pins that `oracle_times` gives up where `oracle_pid_time` does not. It also pins the two cases that must **not** become lenient — this pid's *own* client going back is still no figure, and a pid with no clients is an exact zero rather than unavailable. ### Verified on the GPU host ``` target: 2 tests (with --features ioreport; without it: 0 tests, and cargo still exits 0) baseline: rc=0 passed=1 failed=0 mutated: rc=101 passed=0 failed=1 <- oracle_pid_time put back to totalling every client ``` So the new test discriminates rather than decorates. CI reaches it the same way: `cargo test -p jouleclaw-energy --features ioreport`, which the workflow already notes is double-gated on feature *and* platform. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jouleclaw-energy: another process's GPU client going back is not this pid's problem
All checks were successful
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Successful in 44s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 58s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m1s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 5s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 5s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 44s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 7m35s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Successful in 3m44s
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 59s
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 2m54s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 2m32s
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 23m24s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 5m10s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 52s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 2m20s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m37s
460b7201ba
`a_gpu_span_is_a_sole_users_rail_or_an_exact_zero_or_no_figure` fails
intermittently on the macOS energy job with

  no client's time went back in the oracle's window

`oracle_times` walks every client in the second reading and gives up the whole
result if any one of their counters went back:

    let d = ns.checked_sub(a.clients.get(id).map_or(0, |c| c.1))?;
    all += d;
    if *p == pid { me += d; }

It has to, because its `all` must be exact to compare against a share. But two
of its three callers want only one pid's own time -- both read
`let (child_ns, _, _) = ...` and drop `all` -- so a client of a wholly unrelated
process being destroyed, or its id reused, takes away a figure that never
depended on it. The GPU is shared with whatever else the host runs, which is
precisely when that happens.

`oracle_pid_time` totals the named pid's clients and no others, and those two
callers use it. The strict reader stays where `all` is actually used.

Deterministic test rather than waiting for a host client to vanish: it builds
the two readings, with this pid's client advancing 5 ms while another process's
goes back, and pins that `oracle_times` gives up where `oracle_pid_time` does
not. It also pins the two cases that must NOT become lenient -- this pid's own
client going back is still no figure, and a pid with no clients is an exact zero
rather than unavailable.

Verified on the GPU host, with the feature the file is gated behind:
`--features ioreport` (without it the target is 0 tests and cargo still exits 0).
Baseline passed=1; with `oracle_pid_time` mutated back to totalling every client
the new test fails, so it discriminates rather than decorates.

Co-Authored-By: Claude Opus 5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!278
No description provided.