Files
cluster-knaster/docs/adr/0006-legacy-gpus-llamacpp-tts-auf-ada.md
T
Robert RappandClaude Opus 5.5 cdf0bb63e3
ci / test (push) Successful in 28s
benchmark: Task 3.3 auf gpu-pve48 gemessen (llama.cpp, whisper.cpp, Piper), ohne Strommessung
- Katalog: vram_gb für Qwen3-Embedding, Qwen3-4B und Qwen3-8B gemessen, Messwerte als note
- ADR-0006: Nachtrag „Benchmark“ mit Tabellen und Empfehlung zur M4000
  (ja für STT auf pve52, auf pve44/46/48 vorerst nein)
- Plan: Task 3.3 abgehakt, Strommessung, Dialektsätze und D131/D133 offen

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:19:28 +02:00

77 lines
7.9 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.
# ADR-0006: Alte GPUs nur für llama.cpp, M4000 vorerst außer Betrieb, TTS auf Ada und CPU
- Status: angenommen
- Datum: 2026-10-12
## Kontext
- PyTorch unterstützt Maxwell und Pascal seit 2.8 nur noch in den cu126-Builds. **PyTorch 2.14 ist die letzte Version mit CUDA-12.x-Wheels** (Ankündigung vom 04.09.2026), danach geht es nur noch über einen eigenen Build.
- Pascal hat weder bf16 noch schnelles FP16, und FlashAttention fehlt. Qwen3-TTS 1.7B erreicht auf einer Tesla P40 nur **RTF ~7,3** (Referenz-Implementierung, gemessen von tinycomputers.io). P2000 und M4000 sind schwächer.
- llama.cpp unterstützt Maxwell und Pascal mit CUDA 12 weiterhin. FlashAttention läuft dort auch auf Maxwell.
- Für die M4000 gibt es keine direkten Messungen. Geschätzt liegt sie bei 7B Q4 auf 12–25 Token/s, bei 120 W pro Karte. Die P2000 decken Embedding, Rerank und Verifier bereits ab.
## Entscheidung
1. **Engine-Grenzen im Katalog** (`catalog/models.yaml → engines`): `pytorch` ab Compute Capability 7.5, `vllm` ab 7.0, `llamacpp` ab 5.0. Das Placement setzt PyTorch-Workloads damit nie auf Maxwell/Pascal.
2. **M4000 vorerst außer Betrieb** (`disabled: true` im Inventar). Wieder aufgenommen werden sie nur nach `llama-bench` plus Strommessung am Deployment-Tag, und dann nur für llama.cpp-Rollen.
3. **TTS:**
- `tts-de`: Piper auf der CPU im Infra-LXC. Schnell, robust, ohne GPU, zugleich Fallback.
- `tts-de-hq`: Qwen3-TTS 1.7B (Apache 2.0, Deutsch, Stimmenklonen) in bf16 auf `gpu-flex`, im Wechsel mit Training und `tier1-flex`. Wenn TTS aktiv ist, sinkt der vLLM-Anteil am VRAM auf ~55 %.
- Kein TTS auf P2000 oder M4000.
## Folgen
- Bei `gpu-flex` muss sich der Lifecycle die Karte mit TTS teilen. Während des Trainings gehen sowohl `tier1-flex` als auch `tts-de-hq` auf `unavailable`, und LiteLLM fällt auf `tts-de` zurück.
- Die tatsächlichen RTF-Werte misst `knaster bench tts` beim Deployment. Sie ersetzen die Schätzungen im Katalog.
## Nachtrag 2026-10-12: Ada-Rechner bleiben Windows (D3, vorgeschlagen, Bestätigung offen)
- Die beiden RTX 4000 Ada (20 GB) stecken nicht in einem Proxmox-Knoten, sondern je eine in den Windows-Arbeitsplätzen GODE-PC-05 und GODE-PC-06 (64 GB RAM). Sie bleiben Windows, Mitarbeitende haben tagsüber Vorrang.
- Vorschlag: `LocalLLMWorker.ps1` mit llama-server (CUDA) meldet sich über die Worker-Registry v2. `tier1-general` (gode-pc-05) und `tier1-flex` (gode-pc-06) lösen auf einen Worker auf, der online ist, sonst auf Stufe 0 über den LiteLLM mit PSE.
- In `sites/knaster/registry.yaml` behalten die Ada-Slots vorerst ihre Engine, nur `pve_node` und `vmid` entfallen. Die Umstellung folgt in Task 6.4.
- Folgen: vLLM und PyTorch laufen unter Windows nicht nativ. `tts-de-hq` (Qwen3-TTS), Multi-LoRA und QLoRA auf `gpu-flex` warten auf eine spätere WSL2-Entscheidung (Phase 9). Bis dahin trägt `tts-de` (Piper) die Sprachausgabe allein.
## Nachtrag 2026-10-12: Benchmark (Task 3.3, ohne Strommessung)
Gemessen in `gpu-pve48` (pve48, VM 248: 4 vCPU i7-6700, 12 GB RAM, Treiber 580.178.04), beide Karten nacheinander, nie gleichzeitig.
- **Builds:** llama.cpp `b6000` (Commit `4762ad7`, Compose-Pin aus `deploy/compose/gpu-llamacpp`), `.devops/cuda.Dockerfile` Stufe `build`, `CUDA_VERSION=12.4.0`, `CUDA_DOCKER_ARCH=52;61`. whisper.cpp `v1.9.5` (Commit `d1be6fd`) auf `nvidia/cuda:12.4.0-devel-ubuntu22.04`, `CMAKE_CUDA_ARCHITECTURES=52;61` (braucht `-Wl,--allow-shlib-undefined`, sonst fehlt `libcuda` beim Linken im Container).
- **Modelle** (liegen in `/srv/models` von `gpu-pve48`, dort auch `SOURCES.txt`):
| Datei | Quelle (Hugging Face, Revision) | SHA-256 |
|---|---|---|
| `Qwen3-Embedding-0.6B-Q8_0.gguf` | `Qwen/Qwen3-Embedding-0.6B-GGUF@370f27d` | `06507c7b42688469c4e7298b0a1e16deff06caf291cf0a5b278c308249c3e439` |
| `Qwen3-4B-Q4_K_M.gguf` | `Qwen/Qwen3-4B-GGUF@bc64014` | `7485fe6f11af29433bc51cab58009521f205840f5b4ae3a32fa7f92e8534fdf5` |
| `Qwen3-8B-Q4_K_M.gguf` | `Qwen/Qwen3-8B-GGUF@7c41481` | `d98cdcbd03e17ce47681435b5150e34c1417f50b5c0019dd560e4882c5745785` |
| `ggml-large-v3-turbo.bin` (nach der Messung gelöscht, nicht im Katalog) | `ggerganov/whisper.cpp@5359861` | `1fc70f774d38eb169993ac391eea357ef47c88757ef72ee5943879b7e8e2bc69` |
**llama.cpp** (`llama-bench`, `-ngl 99`, Werte t/s ohne/mit Flash-Attention; VRAM = belegter Speicher mit `llama-server` beim Katalog-Kontext). Als „7B Q4“ wurde das Katalogmodell `qwen3-8b-q4km` (8B) gemessen.
| Karte | Modell | pp512 | tg128 | VRAM (Kontext) |
|---|---|---|---|---|
| M4000 (CC 5.2) | Qwen3-Embedding 0.6B Q8 | 929 | – | 2,8 GiB (8192, `-ub 8192`) |
| P2000 (CC 6.1) | Qwen3-Embedding 0.6B Q8 | 1009 | – | 2,8 GiB (8192, `-ub 8192`) |
| M4000 | Qwen3-4B Q4_K_M | 197 / 204 | 15,1 / 15,3 | 4,1 GiB (8192) |
| P2000 | Qwen3-4B Q4_K_M | 271 / 275 | 14,5 / 14,8 | 4,1 GiB (8192) |
| M4000 | Qwen3-8B Q4_K_M | 115 / 118 | 10,0 / 10,1 | 7,7 GiB (16384) |
| P2000 | Qwen3-8B Q4_K_M | 152 / 135 | 9,0 / 8,2 | **passt nicht** bei 16384 (KV-Cache scheitert), nur mit 512 Kontext (4,9 GiB) |
**whisper.cpp** `large-v3-turbo`, `-l de`, Standard-Dekodierung (Beam 5), Testaudio selbst mit Piper erzeugt (Hausverwaltungs-Brief, keine Kundendaten, danach gelöscht). Rechenzeit ohne Modell-Laden (Laden: P2000 1,1 s, M4000 0,7 s; ein Server lädt nur einmal), Median aus 3 Läufen nach einem Aufwärmlauf:
| Karte | 10-s-Clip | 33-s-Clip, umgerechnet je 10 s | VRAM | Flash-Attention aus |
|---|---|---|---|---|
| P2000 | 3,5 s | 2,5 s | 2,0–2,2 GiB | 3,9 s bzw. 2,9 s |
| M4000 | 2,7 s | 2,1 s | 2,0–2,2 GiB | 3,2 s bzw. 2,3 s |
Erkennung fehlerfrei bis auf „Milltonnen“ (statt „Mülltonnen“); synthetische Sprache ist leichter als echtes Diktat. Zum Vergleich der Dienst `nex-stt` auf der M4000 in `gpu-pve52` (v1.9.4, Task 6.2): 10 s → 2,94 s.
**Piper** (`knaster bench tts` gegen das Image aus `deploy/docker/tts-piper.Dockerfile`, `de_DE-thorsten-medium`, 4 vCPU): RTF 0,17 bei 241 Zeichen (≈ 17 s Audio, 2,9 s Rechenzeit), RTF 0,11 bei 596 Zeichen (≈ 33 s Audio, 3,6 s).
**Leistungsaufnahme laut GPU-Sensor** (`nvidia-smi`, nur die Karte, keine Steckdosenmessung): M4000 Leerlauf 13,5 W (P8), unter llama.cpp 94–102 W, unter whisper 92–99 W. P2000 Leerlauf 6,5 W, unter Last 46–52 W (Grenze 75 W). Ohne Persistence-Modus zeigt ein einzelner `nvidia-smi`-Aufruf kurz P0 mit 46 W bzw. 20 W an; erst nach einigen Sekunden fällt die Karte auf P8.
Weitere Befunde:
- **CC 5.2 rechnet:** llama.cpp b6000 und whisper.cpp 1.9.5 laufen mit CUDA 12.4 auf der M4000, Flash-Attention eingeschlossen.
- Die Token-Erzeugung (tg) ist auf beiden Karten etwa gleich schnell und liegt deutlich unter der Speicherbandbreite. Die Karte ist dabei voll ausgelastet (P2000 99 %), es liegt also nicht an der CPU der VM. b6000 ist über ein Jahr alt (aktuell `b11574`); vor einer Anhebung des Compose-Pins nachmessen.
- Die P2000 hängt in pve48 nur mit PCIe 3.0 x4 an (M4000 x16). Das bremst nur das Laden.
### Empfehlung: M4000 wieder aufnehmen – **ja, aber nur gezielt**
- **pve52 (nur eine M4000): ja**, für STT (whisper.cpp, 2,1 s je 10 s, schneller als die P2000). Ohne sie hat der Knoten keine GPU-Rolle, und die M4000 läuft dort für `nex-stt` ohnehin.
- **pve44, pve46, pve48: vorerst nein** für die heutigen Rollen. Embedding, Rerank und Verifier laufen auf der P2000 gleich schnell oder schneller (Prefill +37 %) bei etwa halber Leistungsaufnahme. Die M4000 lohnt sich dort nur für Rollen, die mehr als 5 GB brauchen: `qwen3-8b-q4km` mit 16k Kontext (7,7 GiB), eine zweite STT-Instanz oder ein zweiter Verifier zur Lastverteilung.
- Nur für llama.cpp und whisper.cpp; PyTorch, vLLM und TTS bleiben ausgeschlossen (Entscheidung 1 und 3 unverändert).
- Eine gesperrte, aber eingebaute M4000 verbraucht im Leerlauf weiter etwa 13 W, solange der Treiber in der VM geladen ist. Bleibt sie dauerhaft ungenutzt, ausbauen.
- Vorbehalt: Die Steckdosenmessung je Knoten (Leerlauf und Volllast) steht aus. Das Flag `disabled` im Inventar ist nicht geändert; die Freigabe für pve52 setzt der Nutzer nach dieser Messung.