Files
Lumotia/docs/gpu-tuning/plan.md
Jake 792fb5ea08 agent: dev launcher — own Linux env-var contract, add dev:tauri, doc sweep
The 2026-05-12 engine-slop pass removed runtime std::env::set_var mutation from src-tauri/src/lib.rs and replaced it with warn_if_x11_env_unset_on_wayland. With no launcher owning the contract, Linux Wayland dogfood was about to regress.

run.sh:
- now owns Linux launcher env defaults via case "$(uname -s)"
  LIBCLANG_PATH=/usr/lib64/llvm21/lib64 (user-set wins)
  WEBKIT_DISABLE_DMABUF_RENDERER=1 (always on Linux; user-set wins)
  GDK_BACKEND=x11, WINIT_UNIX_BACKEND=x11 (Wayland only; user-set wins)
- 60s Vite readiness timeout
- detects early Vite exit (kill -0 + wait) instead of hanging forever
- trap installed before wait so Ctrl-C cleans up
- args forwarded: ./run.sh --release etc.
- non-exec final Tauri launch preserved so cleanup trap fires

package.json:
- "dev:tauri": "./run.sh" — canonical discoverable dev command

Docs:
- README, dev-setup, architecture-map runtime + launcher pages updated with the new contract; canonical command is npm run dev:tauri (./run.sh as direct equivalent)
- dev-launcher-and-scripts.md replaces the incorrect "kills process group" claim with honest "kills the spawned npm process"
- dev-setup.md path /CORBEL-Projects/magnotia → /CORBEL-Projects/transcription-app
- gpu-tuning/plan.md gets a superseded note rather than rewriting the original rationale
- engine-slop-residuals.md gains Area F (packaged-binary launcher contract) with honest wrapper-vs-.desktop trade-off documented

Verification: bash -n run.sh; shellcheck clean; cargo check -p magnotia green; npm pkg get 'scripts.dev:tauri' returns "./run.sh"; stale-ref sweep clean across living docs.
2026-05-12 22:05:33 +01:00

365 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Magnotia — GPU Tuning & Community Config Plan
*Implementation spec for the first three phases of the GPU kernel tuning roadmap. The full five-phase roadmap is pinned in memory; this document scopes the MVP subset that ships real value without pulling in `ggml`-dedup or agentic-search prerequisites.*
## Scope
**IN** (this document):
- Phase 1 — Advanced GPU tuning settings panel (exposing GGML env vars)
- Phase 2 — `magnotia-bench` local autotuning CLI
- Phase 3-lite — `magnotia-configs` community repo with manual-PR workflow (no CI replay)
**OUT** (pinned to memory for later):
- Phase 4 — custom SPIR-V shader drops (blocked on `ggml`-dedup)
- Phase 5 — Karpathy-style agentic autotuning
- CI replay for community repo (defer until spam / bad configs become a real problem)
This subset captures roughly 85% of the perceived value for ~20% of the total effort. The deferred pieces are where complexity explodes; the MVP stops before it.
---
## Phase 1 — Advanced GPU tuning settings panel
**Effort**: 12 days.
**What ships**: Settings → Advanced → GPU Tuning collapsible section with toggles for GGML env vars. Env vars are applied at app startup before any GPU backend initialises. Per-profile storage; restart required to take effect.
### Toggles shipped at MVP
| UI label | Env var | Default | When users enable |
|---|---|---|---|
| Disable cooperative matrix | `GGML_VK_DISABLE_COOPMAT` | off | "Inference hangs" on RDNA2 / buggy Mesa versions |
| Force FP32 math | `GGML_VK_FORCE_FP32` | off | "Garbage transcripts" on Intel Arc / older NVIDIA |
| Disable FP16 ops | `GGML_VK_DISABLE_F16` | off | Silent-fail on some Mesa 22.x builds |
| Disable integer dot product | `GGML_VK_DISABLE_INTEGER_DOT_PRODUCT` | off | "Random NaN" on RDNA2 with certain drivers |
| Enable Vulkan validation | `GGML_VK_VALIDATE` | off | Diagnostic only; impacts performance |
Metal / CUDA counterparts slot in when those backends grow in Magnotia. Today Magnotia is Vulkan-only.
### Design
- New `SettingsState.gpuTuning: { disableCoopmat: boolean, forceFp32: boolean, disableF16: boolean, disableIntegerDotProduct: boolean, enableValidation: boolean }` in [src/lib/types/app.ts](../../src/lib/types/app.ts)
- All defaults `false` in [src/lib/stores/page.svelte.ts](../../src/lib/stores/page.svelte.ts)
- Persistence uses the existing `save_preferences` → SQLite `magnotia_preferences` path
- Backend process env must be established before GPU backend initialisation. **Superseded note (2026-05-12):** runtime `std::env::set_var` mutation and the old `ensure_x11_on_wayland` pattern were removed from `src-tauri/src/lib.rs`; launcher/wrapper processes now own env-var setup. Preserve this startup-order requirement when revisiting GPU tuning, but do not reintroduce in-process env mutation.
- Settings UI shows a sticky "Restart required for changes to take effect" banner when any toggle has drifted from its launch-time value
- A "Reset to defaults" button zeroes all toggles
### Acceptance
- Toggling "Disable cooperative matrix" on and restarting → `vulkaninfo` (or GGML debug logs) confirms the knob is honoured at backend init
- Default all-off produces identical performance + transcription output to the current `main` (smoke test)
- An integration test with a fake settings fixture confirms env vars are set before `AppState` initialises
---
## Phase 2 — `magnotia-bench` local autotuning CLI
**Effort**: 35 days.
**What ships**: New workspace binary `crates/bench/` producing a `magnotia-bench` executable. User runs it once post-install; output lands at `~/.magnotia/gpu-profile.toml` with the best-scoring config for their hardware. Settings page gets an "Apply auto-tuned profile" button that consumes the TOML and updates the Phase 1 toggles.
### CLI surface
```
magnotia-bench --quick # bundled 20s sample + reference transcript
magnotia-bench --model <path> --audio <wav> --transcript <txt>
magnotia-bench --compare <profile.toml> # benchmark a specific profile vs default
```
### Execution model
Grid-search via **subprocess spawning**. Each config variant runs in a child process with its own env vars — because env vars must be set at process startup; you cannot safely mutate GGML's runtime state once it's initialised. The parent serialises variants, spawns a child per variant, waits for each to exit with a JSON line on stdout, aggregates and ranks.
### Search strategy (not naive combinatorial)
1. Run baseline (all defaults).
2. Run each single-flag variant against baseline.
3. Take the top-3 single flags by RTF improvement with zero WER drift.
4. Combine pairwise.
5. Top-scored composite config wins.
This gives us ~915 subprocess runs instead of the ~32 a full combinatorial sweep would need; converges on local optima without the combinatorial explosion.
### Metrics
- **Real-time factor (RTF)** = `audio_seconds / inference_wall_seconds`. Lower is better.
- **Word error rate (WER)** against the ground-truth transcript. Any config with >0.5% WER drift from baseline is rejected regardless of RTF improvement.
- **Peak VRAM** (optional, best-effort via `nvidia-smi` / `rocm-smi` sampling).
### Runtime
~515 minutes on typical hardware. Progress bar + ETA rendered to stderr so stdout stays machine-readable.
### Bundled fixture
A 20-second public-domain speech clip with a known-good reference transcript, committed to `crates/bench/fixtures/`. Source: LibriVox recording (CC0).
### Output schema (`gpu-profile.toml`)
```toml
[benchmarked_at]
timestamp = "2026-04-21T14:32:00Z"
magnotia_version = "0.1.0"
model = "whisper-distil-large-v3"
[hardware]
gpu_name = "NVIDIA GeForce RTX 4070"
vram_mb = 12282
driver = "nvidia 550.120"
os = "linux"
mesa = ""
[baseline]
rtf = 0.043
wer = 0.028
[best]
rtf = 0.031
rtf_improvement = 0.279 # 27.9% faster
wer = 0.028
[best.env]
GGML_VK_DISABLE_COOPMAT = "0"
GGML_VK_FORCE_FP32 = "0"
# … full flag set, including unchanged ones, for reproducibility
```
### Crate layout
```
crates/bench/
├── Cargo.toml
├── fixtures/
│ ├── librivox-sample.wav
│ └── librivox-sample.txt
└── src/
├── main.rs # CLI + parent process
├── runner.rs # subprocess harness (child entry gate: MAGNOTIA_BENCH_RUN=1)
├── matrix.rs # grid-search + top-k logic
├── metrics.rs # RTF + WER + optional VRAM sampling
└── profile.rs # TOML serialise
```
Depends on `magnotia-transcription` + `magnotia-llm` + `magnotia-audio` as path deps so it reuses the existing model-loading code.
### Acceptance
- `magnotia-bench --quick` runs unattended to completion on a fresh install
- Produces a valid `gpu-profile.toml`
- "Apply auto-tuned" button in Settings consumes the TOML and updates Phase 1 toggles (restart banner fires as expected)
- Re-running with `--compare <profile>` produces reproducible-enough numbers (RTF within 5% run-to-run)
---
## Phase 3-lite — `magnotia-configs` community repo
**Effort**: 3 days (1 for repo + seeds, 2 for Magnotia-side fetch + apply UI).
**What ships**: A separate public GitHub repo `magnotia-configs` (not part of the magnotia main repo) seeded with 23 curated configs. Magnotia's Settings page gets a "Browse community configs" button that fetches matching configs for the user's detected hardware.
### Repo structure
```
magnotia-configs/
├── README.md # pitch + how to benefit
├── CONTRIBUTING.md # required fields, benchmark protocol, fork/PR flow
├── SCHEMA.md # TOML schema documentation
├── index.json # manifest for Magnotia to discover configs
└── configs/
├── nvidia/
│ ├── rtx-3060-12gb-linux.toml
│ └── rtx-4070-linux.toml
├── amd/
│ └── rx-6700xt-mesa-23-linux.toml
└── intel/
└── arc-a770-windows.toml
```
### Config TOML
Extends Phase 2's `gpu-profile.toml` schema with an `[attribution]` section:
```toml
[attribution]
submitter = "@username"
notes = "Tested with 1-hour continuous dictation session, no crashes."
```
### Contribution flow (manual, honour-system MVP)
1. User runs `magnotia-bench` on their hardware.
2. User runs `magnotia-bench --compare` against baseline to confirm improvement isn't noise.
3. User forks `magnotia-configs`, commits their TOML under `configs/<vendor>/`, opens PR.
4. Maintainer reviews format + plausibility, merges.
5. No CI replay — revisit if spam becomes a problem.
### Magnotia integration
- New Tauri command `fetch_community_configs(gpu_fingerprint)` — HTTPS GET `https://raw.githubusercontent.com/<org>/magnotia-configs/main/index.json` for the manifest, then fetches matching TOMLs
- Fingerprint match: GPU name substring + VRAM tier (e.g., `"RTX 3060"` + `"12gb"`)
- Settings "Browse community configs" button lists matches with submitter, claimed RTF improvement, and a preview of the toggle deltas
- Applying a config updates Phase 1 toggles AND stores provenance (source = `"community"`, submitter, fetch date)
### What we explicitly skip at MVP
- **No CI replay**. Maintainer eyeballs + honour system. Revisit past ~50 configs or on abuse.
- **No automated upload from `magnotia-bench`**. User always commits + PRs manually. Zero privacy concerns, zero spam surface.
- **No sophisticated fingerprint normalisation**. Substring matching is sufficient.
### Acceptance
- Repo exists with README + CONTRIBUTING + 23 seed configs
- Magnotia Settings fetches + lists + applies a community config end-to-end
- "Revert to default" path works (Phase 1's reset)
---
## User experience — the one-click path
This is the UX the three phases together enable. All three are prerequisites; Phase 3-lite is what turns "run a CLI" into "click a button."
### First-launch onboarding nudge
After the existing first-run model download, Magnotia surfaces a non-modal card:
```
🎛 GPU Optimisation
Detected: NVIDIA RTX 4070 (12 GB) · Linux Wayland
Current: Default GGML kernels
[ Auto-optimise ] [ Show advanced ] [ Skip ]
```
"Auto-optimise" triggers the hybrid flow below. "Show advanced" expands the Phase 1 toggle panel directly. "Skip" dismisses; user can always come back via Settings.
### The "Auto-optimise" flow
Two steps, in this order:
**Step 1 — Community config check (instant, ~2 s)**
Magnotia fingerprints the GPU and queries the `magnotia-configs` manifest for matches. If a match exists, a preview card appears:
```
┌─────────────────────────────────────────────┐
│ Community config available │
│ │
│ From: @someuser │
│ Claimed: 27% faster · 0% accuracy drift │
│ Tested: 2026-04-21, driver nvidia 550 │
│ │
│ Changes 2 settings: │
│ • Cooperative matrix: on → off │
│ • Integer dot product: on → off │
│ │
│ [ Apply (restart required) ] [ Cancel ] │
└─────────────────────────────────────────────┘
```
Apply → settings persist → restart prompt → done. 15 seconds end-to-end.
**Step 2 — Fallback to local benchmark**
If no community match, or the user prefers their own measurement:
```
┌─────────────────────────────────────────────┐
│ No community config for your hardware yet │
│ │
│ We can benchmark your machine to find the │
│ best settings. Takes ~8 minutes; runs in │
│ the background while you keep using Magnotia. │
│ │
│ [ Benchmark my GPU ] [ Skip ] │
└─────────────────────────────────────────────┘
```
Kicks off `magnotia-bench` as a background process. Magnotia keeps working during the run.
### Progress UI during benchmark
Non-modal. Status chip in the lower-right of the main window:
```
⚙ Benchmarking GPU · 4 of 12 tested · ~5 min remaining [ cancel ]
```
On completion, a toast:
```
Your GPU is 27% faster with the new config. [ Review → ]
```
Review opens the same preview card as the community-config flow, with the same Apply / Cancel options.
### After applying
Settings shows the active config's provenance:
- `Using community config · applied 2026-04-21 · by @someuser`
- `Using auto-tuned config · benchmarked 2026-04-21`
- `Using defaults`
Plus a "Revert to previous config" button, active for 7 days after any change, in case the new config misbehaves in real use (silent accuracy drift, crashes on long sessions, etc.) that the benchmark didn't catch.
### Optional — sharing back to the community
After a successful local benchmark that shows meaningful gains, Magnotia prompts:
```
┌─────────────────────────────────────────────┐
│ Share your config with the community? │
│ │
│ Your RTX 4070 tuning got you 27% faster. │
│ Other RTX 4070 users would benefit. │
│ │
│ Shared data: GPU name, driver version, OS, │
│ config flags, benchmark numbers. │
│ NOT shared: personal info, audio, anything │
│ that identifies you beyond the GitHub fork. │
│ │
│ [ Review payload ] [ Create PR ] [ No ] │
└─────────────────────────────────────────────┘
```
"Create PR" opens the user's browser to `github.com/…/magnotia-configs/new/main` with the TOML prefilled in the PR body. User finishes the submission on GitHub (still honour-system; no automated uploads, no telemetry).
### Non-GPU / integrated-only fallback
If `sysinfo` reports no dedicated GPU or Vulkan isn't available, the card replaces itself with:
```
🎛 GPU Optimisation
No dedicated GPU detected — Magnotia is using CPU inference.
GPU tuning doesn't apply to this setup.
```
No nag, no hidden settings, no broken experience.
### Yes, "one click" is achievable
For users whose GPU has a community-contributed config, the experience is **literally one click** (the Apply button), plus a restart. ~15 seconds.
For users without a community match, the experience is **two clicks** (trigger bench → apply results on completion), with a passive ~8-minute background wait in between.
For users on integrated graphics / no GPU, the experience is **zero clicks** — Magnotia tells them GPU tuning doesn't apply and moves on.
---
## Sequencing
Strict linear: Phase 1 → Phase 2 → Phase 3-lite. Each phase merges to `main` and gets dogfooded before the next starts.
- Phase 1 is a prereq for Phase 2 — `magnotia-bench`'s output needs the Phase 1 settings schema to be its consumption target.
- Phase 2 is a prereq for Phase 3-lite — the community repo's config TOML schema **is** Phase 2's output schema (with an added `[attribution]` section).
## Shelved with rationale
- **Phase 4 — custom SPIR-V shader drops.** Blocked on `ggml`-dedup workstream. Pinned in memory.
- **Phase 5 — agentic (Karpathy-style) autotune.** Phase 2's grid search produces schema-compatible results, so Phase 5 can drop in later without a schema break. Pinned.
- **Phase 3's CI replay.** Defer until spam / bad-config abuse is a real problem rather than a hypothetical one. Honour-system PR review is sufficient for the MVP community.
- **`magnotia-bench` automated upload.** Deliberately manual for MVP — removes all privacy / spam / rate-limiting concerns. Revisit when the community volume justifies the infrastructure.