jouleclaw-energy: another process's GPU client going back is not this pid's problem #278
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/process-gpu-oracle-pid-time"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
a_gpu_span_is_a_sole_users_rail_or_an_exact_zero_or_no_figurefails intermittently on the macOS energy job withWhy
oracle_timeswalks every client in the second reading and gives up the whole result if any one of their counters went back:It has to, because its
allmust be exact to compare against a share. But two of its three callers want only one pid's own time — both readlet (child_ns, _, _) = ...and discardall— 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_timetotals the named pid's clients and no others, and those two callers use it. The strict reader stays whereallis 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_timesgives up whereoracle_pid_timedoes 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
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 `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]>