Commit b48ee82a authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: perfd - 'measure' now PINS the CPU frequency (min=max) + per-hold overrides

Andrey's observation on the first perfd-held run: CPU boosting to 4.9 GHz,
100 C. Calibration (openssl all-core): the i9-11900K spikes 4.8 GHz @ 85 C,
hits 100 C within seconds and throttles to a wobbling 3.2-3.5 GHz - the
'performance' boost bias is itself a nondeterminism source AND rides Tjmax.
- measure profile: CPU pinned via sysfs scaling_min=max (default 3.2 GHz =
  the measured all-core throttle equilibrium, so the pin holds even in the
  worst phase and runs cooler; PERFD_CPU_LOCK_KHZ) + the existing GPU lock.
  PPD 'performance' hold now only backs the max profile.
- HOLD accepts bounds-checked per-hold overrides (HOLD measure cpu=KHZ
  gpu=MHZ; perfctl passes them through) so lock-value calibration needs no
  daemon reconfiguration/sudo.
- Holds now per-connection with values from the newest holder of the
  winning profile; STATUS extended.
User-mode tested: override parsing/apply, bounds rejection, permission
errors surfaced, auto-release. Root paths activate on reinstall.
Co-authored-by: 's avatarClaude Opus 4.8 <claude-opus-4-8@anthropic.com>
Co-authored-by: 's avatarClaude Fable 5 <claude-fable-5@anthropic.com>
parent 74d8341c
...@@ -24,11 +24,17 @@ install command above when absent (and continues normally). ...@@ -24,11 +24,17 @@ install command above when absent (and continues normally).
perfctl hold max # production profile until Ctrl-C perfctl hold max # production profile until Ctrl-C
Profiles: Profiles:
- `measure` — CPU `performance` + GPU persistence + clocks **locked** - `measure` — CPU frequency **pinned** (`scaling_min=max`, default 3.2 GHz,
(default 2550 MHz, `PERFD_GPU_LOCK_MHZ` in the unit): run-to-run timing `PERFD_CPU_LOCK_KHZ`) + GPU persistence + GPU clocks **locked** (default
reproducibility (±1% instead of ±10% with free-running boost) for per-item 2550 MHz, `PERFD_GPU_LOCK_MHZ`): run-to-run timing reproducibility (±1%
performance evaluation. instead of ±10% with free-running boost) for per-item performance
- `max` — CPU `performance` + GPU persistence, clocks unlocked: throughput. evaluation. Pinned, not `performance`: the i9-11900K at free boost hits
4.9 GHz → 100 °C → throttle wobble within seconds of an all-core phase
(measured 07/17/2026) — boost bias is itself a nondeterminism source.
Per-hold overrides: `perfctl hold measure cpu=3400000 gpu=2400 -- <cmd>`
(bounds-checked; for calibration without reconfiguration).
- `max` — CPU `performance` profile (free boost) + GPU persistence, clocks
unlocked: throughput.
A hold is tied to the client's connection — process exit or crash releases A hold is tied to the client's connection — process exit or crash releases
it automatically (refcounted across concurrent holders; `measure` outranks it automatically (refcounted across concurrent holders; `measure` outranks
......
...@@ -11,6 +11,7 @@ ExecStart=/usr/bin/python3 /usr/local/lib/elphel-perfd/elphel_perfd.py ...@@ -11,6 +11,7 @@ ExecStart=/usr/bin/python3 /usr/local/lib/elphel-perfd/elphel_perfd.py
# Config overrides (defaults live in the script): # Config overrides (defaults live in the script):
#Environment=PERFD_PORT=48890 #Environment=PERFD_PORT=48890
#Environment=PERFD_GPU_LOCK_MHZ=2550 #Environment=PERFD_GPU_LOCK_MHZ=2550
#Environment=PERFD_CPU_LOCK_KHZ=3200000
#Environment=PERFD_GPU_INDEX=0 #Environment=PERFD_GPU_INDEX=0
Restart=on-failure Restart=on-failure
RestartSec=2 RestartSec=2
......
This diff is collapsed.
...@@ -4,11 +4,14 @@ perfctl - unprivileged client for elphel-perfd (127.0.0.1:48890). ...@@ -4,11 +4,14 @@ perfctl - unprivileged client for elphel-perfd (127.0.0.1:48890).
perfctl status one-line daemon/clock status perfctl status one-line daemon/clock status
perfctl ping probe (exit 0 = daemon installed) perfctl ping probe (exit 0 = daemon installed)
perfctl hold <measure|max> hold until Ctrl-C perfctl hold <measure|max> [cpu=KHZ] [gpu=MHZ]
perfctl hold <measure|max> -- CMD [ARGS...] hold until Ctrl-C (overrides optional)
perfctl hold <measure|max> [cpu=KHZ] [gpu=MHZ] -- CMD [ARGS...]
hold for the duration of CMD hold for the duration of CMD
The hold is tied to this process's connection: if perfctl dies, the daemon The hold is tied to this process's connection: if perfctl dies, the daemon
releases automatically. By Claude on 07/17/2026. releases automatically. cpu=/gpu= override the daemon's 'measure' lock
defaults (bounds-checked server-side) - for calibration without
reconfiguration. By Claude on 07/17/2026.
""" """
import os import os
import signal import signal
...@@ -47,16 +50,20 @@ def main(): ...@@ -47,16 +50,20 @@ def main():
if args[0] == "status": if args[0] == "status":
print(ask(f, "STATUS")) print(ask(f, "STATUS"))
return 0 return 0
# hold # hold [cpu=KHZ] [gpu=MHZ] [-- CMD...]
if len(args) < 2 or args[1] not in ("measure", "max"): if len(args) < 2 or args[1] not in ("measure", "max"):
print("perfctl: hold needs a profile: measure | max") print("perfctl: hold needs a profile: measure | max")
return 2 return 2
reply = ask(f, "HOLD " + args[1]) overrides = []
rest = args[2:]
while rest and ("=" in rest[0]) and (rest[0] != "--"):
overrides.append(rest.pop(0))
reply = ask(f, " ".join(["HOLD", args[1]] + overrides))
print("perfctl: " + reply) print("perfctl: " + reply)
if not reply.startswith("OK"): if not reply.startswith("OK"):
return 1 return 1
if len(args) > 2 and args[2] == "--": if rest and rest[0] == "--":
rc = subprocess.call(args[3:]) rc = subprocess.call(rest[1:])
ask(f, "RELEASE") ask(f, "RELEASE")
return rc return rc
print("perfctl: holding '%s' until Ctrl-C ..." % args[1]) print("perfctl: holding '%s' until Ctrl-C ..." % args[1])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment