Commit Graph

11 Commits

Author SHA1 Message Date
drjones
27dcfd0ada Unload every resident Ollama model on yield; widen the confirm window
The confirm barrier surfaced two yields that left 8.2 GB allocated after 3s. Two
separate issues behind that class of failure:

- The yield only unloaded loaded_models[0]. Ollama can hold several models resident
  (OLLAMA_MAX_LOADED_MODELS), so releasing the first left the rest allocated. It now
  unloads every resident model concurrently. This box runs with the limit at 1, so
  the change is defensive here rather than a fix for the observed case.
- The observed 8.2 GB stalls happened while ComfyUI was starting and Ollama had a
  generation in flight; Ollama will not unload mid-request. A 3s ceiling reported a
  timeout for a model that was simply busy finishing. Raised to 10s -- waiting longer
  is the safer failure mode, since the alternative is diffusion allocating into VRAM
  that is still occupied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 09:14:58 -07:00
drjones
63297dc49d Verify autotune knobs against hardware before sweeping
Sweeping a knob the driver ignores measures nothing but benchmark noise, and the
tuner would then confidently report 'best = the highest value tried'. On this box
(driver 595.84) nvidia-settings accepts GPUGraphicsClockOffset/GPUMemoryTransferRate
Offset and silently discards them: assigning 0 reports success and reads back 250.
The ollama profile's core_offset_mhz=35 and mem_offset_mhz=200 have therefore been
doing nothing.

- _knob_effective() applies a probe value and confirms the hardware actually moved
  before any sweep starts, choosing the candidate furthest from the current reading
  (probing with the maximum fails when the card already sits at its top clock).
- Adds discrete clock-lock knobs (lock_mem_mhz, lock_core_max) driven by the card's
  own supported-clock list, since -lmc/-lgc do work where offsets do not.
- Reasoning models return their output in 'thinking' with an empty 'response', which
  the degeneracy check was flagging as corruption. Token count is now the primary
  signal.
- Separates gain-vs-current-setting from gain-vs-slowest-value-tried. Reporting the
  latter as 'gain vs baseline' implied a +102% speedup that nobody would observe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 09:10:06 -07:00
drjones
5431144b2e Add barrier-confirmed yielding, measured residency, persistence and closed-loop tuning
Nine changes, in rough order of how much they affect real behaviour:

1. VRAM yield is now a barrier. Posting keep_alive:0 only asks Ollama to unload;
   measured here, the HTTP call returns in 63ms while the driver takes a further
   77ms to release 14.9GB. Returning inside that window is how ComfyUI ends up
   allocating into VRAM that is still occupied. instant_free_ollama_vram() polls
   NVML until the allocation is actually gone and reports request/confirm split.

2. ComfyUI VRAM is no longer purged 1.5s after every prompt, which forced a full
   checkpoint reload on each workflow iteration. It is held for 30s of genuinely
   empty queue, with an immediate purge when Ollama actually asks for the memory.

3. Cache-hit classification uses achieved bandwidth (size / load duration) rather
   than a fixed `load_duration < 2500ms`. That constant called a 12.9GB model read
   at 2.9GB/s a cold load, and a 0.5GB model read from NVMe a cache hit.

4. Page-cache residency is measured, not assumed. mincore(2) reported 128GB
   resident on a box with 46GB of page cache: the kernel only permits page-cache
   introspection on files you own, and the Ollama blobs are owned by uid ollama,
   for which mincore answers "all resident" instead of failing. Uses cachestat(2)
   where permitted and a randomised read-rate probe elsewhere, labelling which was
   used. Fixed-offset probing was self-fulfilling, so windows are random and cold
   ones are returned with FADV_DONTNEED.

5. Warming is budgeted and ranked by recency/frequency instead of reading every
   file top-to-bottom, which on 64GB of RAM just evicts whatever was warmed first.

6. Telemetry and events persist to SQLite (~0.38 MB/hour) instead of living in a
   50-entry in-memory deque, so /api/analytics/profiles can finally answer whether
   an overclock profile actually delivers more tok/s.

7. Thermal governor walks the overclock back on sustained heat or hardware
   throttling, with hysteresis, fed from the existing sampler.

8. Autotune sweeps a clock offset, benchmarks decode at each step, watches for Xid
   errors and degenerate output, and restores the profile in a finally block.

9. Stock clocks/power/fans are restored on shutdown and via systemd ExecStopPost.
   Nothing previously undid a locked clock or a manually pinned fan.

Also: one shared 1Hz telemetry sampler fanned out to SSE subscribers rather than
every client re-running the whole snapshot; wall-clock timestamps in place of the
event loop's monotonic clock; cached nvidia-smi shell-outs; quieter httpx logging.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 08:57:35 -07:00
drjones
6acf235bd7 Document all HyperSwap features in README and update overclock profiles 2026-08-24 20:54:21 -07:00
drjones
3477d50129 Update overclock profiles with tuned Ollama clocks and fan profile 2026-08-23 13:40:31 -07:00
drjones
f8a8b2fa00 Fix JavaScript syntax error caused by duplicate ram variable declaration in app.js 2026-08-23 09:08:35 -07:00
drjones
a0075d23a7 Fix wiring between overclock profiles, UI controls, and hardware fan actuation 2026-08-23 09:05:20 -07:00
drjones
02c85d778f Visualize VRAM GB and Host RAM Cache GB in real-time tuning graph 2026-08-23 08:58:36 -07:00
drjones
1f198ae10e Add GPU fan control, live telemetry, and per-profile fan curves in HyperSwap dashboard 2026-08-23 08:56:06 -07:00
drjones
850e1aa565 docs: add live dashboard screenshot and iGPU VRAM optimization section 2026-08-22 10:52:08 -07:00
drjones
f909dd23fb Initial commit: HyperSwap GPU Program Swapper with REST API, MCP 2.0, Real-Time Dashboard and Memory Orchestrator 2026-08-22 00:59:40 -07:00