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

16 KiB
Raw Blame History

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
  • All defaults false in 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)

[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:

[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.