# Negativní zjištění — nvidia.hell / ollama Co selhalo, co nefunguje a co jsme zkusili marně. Sesbíráno z incidentů 12.–13. 9. 2026. Plné záznamy jsou v [history.md](history.md), ověřená pozitivní fakta v [knowledge.md](knowledge.md). Rozsah: jen stroj nvidia.hell a ollama. Slepé uličky z PVE migrace tu nejsou — ty jsou v [knowledge.md](knowledge.md). --- ## 1. Pojistky, které selhaly ### earlyoom jako ochrana ollamy — zavrženo, odinstalováno Nasazen 13. 9. ve 14:20, do večera odinstalován. Killoval `llama-server` uprostřed CUDA inicializace a nvidia driver při tom natrvalo ztratil napinovanou host paměť. Po ~15 killech chybělo **9,27 GiB** a ollama nenačetla vůbec nic. Tím vznikla kladná zpětná vazba: leak ubere RAM → práh `-m 10` je blíž → earlyoom zabíjí dřív → další leak. Nakonec umíral každý nový `llama-server` už při 300 MiB RSS. **Poučení:** proti procesu, který drží GPU kontext, je externí zabíječ horší než nic. Náhradou je cgroup strop, který nenechá tlak vzniknout. → [history.md](history.md) 2026-09-13 15:45 ### earlyoom ve výchozí konfiguraci by nezasáhl nikdy Balík byl na stroji nainstalovaný a běžel už před incidentem, jen ve výchozím `-m 10 -s 10`. earlyoom zabíjí **jen když jsou obě podmínky splněné současně**. Ze swapu bylo obsazeno 1,4 z 32 GB, tedy ~95 % volných — podmínka `swap <= 10 %` nemohla nastat. Běžící earlyoom tedy nebyl žádná ochrana. ### earlyoom odvozuje SIGKILL práh jako polovinu zadaného První pokus s `-s 100` dal SIGKILL práh `swap <= 50 %`, takže při 95 % volného swapu by eskalace nikdy nenastala. Musí se psát `-s 100,100`. ### MemoryHigh mezi spotřebou a MemoryMax = past Nastaveno `MemoryHigh=5G` + `MemoryMax=6G`. gemma4 potřebuje host buffer **5901 MiB**, což padlo přesně doprostřed. Výsledek při testu 13. 9. 17:05: ``` memory.events: high 84358 max 0 oom 0 oom_kill 0 memory.peak: 5,46 GiB ``` Cgroup 84 tisíckrát reclaimovala, proces se plazil, tvrdý strop nezasáhl ani jednou a load **visel 600 s bez jediné chybové odpovědi**. Ani neselhal, ani neproběhl. **Poučení:** když má konfigurace „rychle selhat", `MemoryHigh` se nesmí nastavit — ať se narazí rovnou do `MemoryMax`. Odstraněno. → [history.md](history.md) 2026-09-13 17:10 ### systemd-oomd — nepoužito Na stroji není nainstalovaný. Nenasazovali jsme ho: je to PSI varianta téhož principu jako earlyoom, tedy SIGKILL zvenčí, takže se dá čekat týž leak. Neověřeno měřením, jen odvozeno. --- ## 2. Slepé uličky v konfiguraci ollamy ### Ollama nemá admission control Ověřeno z `ollama serve --help` (v0.33.2): **neexistuje proměnná typu „odmítni load, když se nevejde do VRAM"**. Ollama je navržená tak, že přeteče do CPU vždycky. K dispozici je jen `OLLAMA_MAX_LOADED_MODELS`, `OLLAMA_MAX_QUEUE`, `OLLAMA_NUM_PARALLEL`, `OLLAMA_GPU_OVERHEAD`, `OLLAMA_CONTEXT_LENGTH`, `LLAMA_ARG_FIT_TARGET`, `OLLAMA_LOAD_TIMEOUT` — nic z toho není admission control. Jediné skutečné odmítnutí je nenabídat nebezpečné modely. ### `OLLAMA_NO_MMAP` neexistuje Žádost o globální řízení mmapu je [#4895](https://github.com/ollama/ollama/issues/4895), [PR #6854](https://github.com/ollama/ollama/pull/6854) nebyl nikdy sloučen („upstream changes broke this patch"). Lidé to žádají ještě 6/2026. Vypnutý mmap se tedy konfigurací obejít nedá. ### Navýšení RAM problém neřeší Podmínka je `FreeMemory < modelSize + max(8 GB, TotalMemory/10)`. Headroom je tedy **konstanta 7,5 GiB** až do 80 GB RAM. Pro gemma4 (8,9 GiB) je potřeba 16,4 GiB *volné* RAM, takže mmap by zůstal zapnutý až u ~20GiB VM. Důkaz z journalu — tři loady při zcela různé volné paměti, všechny tři `disabling mmap ... headroom="7.5 GiB"`: | čas | `system_free` | |---|---| | 12:09:20 | 8,4 GiB | | 12:44:50 | 3,4 GiB | | 13:00:03 | 115,1 MiB | Volná paměť nikdy nehrála roli. Uživatel proto paměť naopak **ubral** z 11,4 na 9,5 GiB. ### Omezování počtu modelů — zavrženo `OLLAMA_MAX_LOADED_MODELS=1` + `NUM_PARALLEL=1` + `MAX_QUEUE=8` byly v plánu a uživatel je oprávněně vyhodil: stroj shodila **hostitelská RAM, ne VRAM** (karta má 16 GB volných), a 49 requestů z nanobotu nepoložilo stroj frontou, ale sekvencí loadů — na což `MAX_QUEUE` vůbec nesahá. Byly to škrty bez vazby na příčinu, které by degradovaly běžný provoz. ### Upgrade ollamy problém neřeší Nainstalovaná 0.33.2, nejnovější v0.34.0 (5. 9. 2026). Release notes obsahují jen ChatGPT Desktop, structured output na Apple Silicon a OpenAI tool search — **nic o scheduleru ani mmapu**. ### `OLLAMA_KV_CACHE_TYPE=q4_0` rozbíjí modely Proměnná je globální a shodí modely s `n_embd_head_k=80`. `granite-code` kvůli ní 12. 9. spadl **6× po sobě** na `K cache type q4_0 with block size 32 does not divide n_embd_head_k=80` — a každý pokus přitom nastartoval llama-server a načetl 1,9 GiB s vypnutým mmapem. Stále nastaveno, neopraveno. ### gemma4 se na tenhle stroj nevejde a nikdy nevejde Není to otázka velikosti modelu. Architektura Per-Layer Embeddings drží embeddingy na CPU **záměrně**: ``` | - CUDA0 (RTX 4060 Ti) | 16076 = 15951 + (2966 = 2829 + 29 + 107) + -2842 | | - Host | 5938 = 5901 + 0 + 37 | ``` Do VRAM jde 2966 MiB z 16076 volných, zatímco host drží 5901 MiB. Kontraintuitivní důsledek: **čím prázdnější karta, tím spíš se mmap vypne** — při těsné VRAM zůstává zapnutý. Ollama si navíc CPU buffer započítá do předpovědi `predicted="9.4 GiB"` jako by šel celý do VRAM. --- ## 3. Chyby v systemd konfiguraci ### `StartLimitIntervalSec` / `StartLimitBurst` v `[Service]` se tiše ignorují Patří do `[Unit]`. `RestartSec` naopak do `[Service]`. Property se navíc jmenuje `RestartUSec` — `systemctl show -p RestartSec` nevrátí nic. ### `MemoryMax` sám o sobě nelimituje swap Mapuje na `memory.max`, což je strop **jen pro RAM**. Po jeho dosažení kernel proces nezabije, ale začne ho swapovat. Se swapem 32 GB to znamená thrashing místo rychlého OOM killu. Tvrdý strop vznikne až s `MemorySwapMax`. ### Instalátor ollamy přepisuje unit soubor `install.sh` (ř. 215) bezpodmínečně přepíše `/etc/systemd/system/ollama.service` přes `tee`. Do `ollama.service.d/` nesahá, takže vlastní nastavení patří do drop-inu. Zavrženo: držet kopii unitu a po upgradu ji kopírovat zpět — konzervuje i upstream řádky (`ExecStart`, `User`, `PATH`), takže upstream změna se ztratí. ### Limity z 12. 9. ze stroje nevysvětleně zmizely Zapsány v 21:10, v 21:44 už v `override.conf` nebyly (zůstaly jen `StartLimit*`, `RestartSec` a `Environment`). Při incidentu 13. 9. proto `systemctl show ollama` hlásil `MemoryMax=infinity`. **Příčina zmizení nebyla nikdy zjištěna.** Proto teď existuje záloha `override.conf.bak-20260913` a kontrola limitů je součástí ověření. ### Překlep `LLAMA_MAX_LOADED_MODELS` V drop-inu je zakomentovaný řádek `Environment="LLAMA_MAX_LOADED_MODELS=1"`. Proměnná se jmenuje `OLLAMA_MAX_LOADED_MODELS` — nefungovala by ani po odkomentování. --- ## 4. Co nástroje neukážou ### Napinovanou paměť neukáže `ps`, `nvidia-smi` ani `systemd-cgtop` Při leaku 9,27 GiB hlásily: - `ps -eo rss` přes všechny procesy dohromady ~250 MB - `nvidia-smi`: 2 MiB / 16380 MiB, **No running processes found** - `systemd-cgtop`: žádná služba nic nedrží - `/proc/meminfo`: `AnonPages` 135 MiB, ale `Active(anon)+Inactive(anon)` 9,4 GiB Jediné, co to ukáže, je rozdíl `nr_foll_pin_acquired − nr_foll_pin_released` ve `/proc/vmstat`. Na to je teď skript `~/bin/nvidia-reload` na nvidia.hell. ### Nedopočet paměti v `sar` z 13. 9. byl tentýž leak Záznam z 13:40 skončil otevřeným bodem: `kbmemused` 10,6 GB proti `kbanonpg` 54–126 MB, `kbcached` 975 MB, `kbslab` 187 MB — ~9,4 GB nesedělo do žádné kategorie a po rebootu to nešlo dovyšetřit. **Vysvětleno až v 15:45:** byla to právě ta napinovaná paměť. `sar` pro ni nemá sloupec. ### Restart ollamy leak neuvolní a vystrčí ho z cgroup Během incidentu je leak účtovaný cgroup ollamy (`memory.current` 5,59 GiB při `anon` jen 15,9 MB), takže ho `MemoryMax` drží. Po `systemctl restart ollama` je `foll_pin` delta **identická**, ale `memory.current` spadne na 18 MB a paměť si nese `system.slice`. Kontejnerování tedy platí jen do prvního restartu; pak leak uteče ze stropu a trvale ubere stroji RAM. Uvolní ho až teardown nvidia driveru nebo reboot. ### Proxmox ballooning je pro LLM stroje nevhodný `pvestatd` (`auto_ballooning`) počítá cíl z **volné paměti hostitele**, ne z tlaku v guestu. `maxchange` je 100 MB na cyklus á 10 s, tedy ~10 MB/s: navýšení o 8 GB trvá ~14 minut, zatímco načtení modelu 17 s. Během OOM incidentu zůstalo `total` na 7,4 GiB, přestože guest padl na 136 MB volných. --- ## 5. Chybné závěry, které jsme museli opravit ### „Viníkem je LibreChat" — ne První diagnóza (13:40) označila LibreChat za spouštěč. Uživatel zatuhnutí reprodukoval i z `ollama` CLI, čímž závěr padl. LibreChat byl jen zesilovač: po 15minutovém timeoutu load okamžitě zopakoval při 115 MiB volných. Spouštěčem je samotný model. ### „Embedding drží LibreChat" — ne `qwen3-embedding:0.6b` drží **nanobot.hell (192.168.4.64)**, ne LibreChat (192.168.4.45). Periodické `POST /api/embed`. Nanobot je zároveň zdrojem dávek desítek requestů přes ~10 různých modelů během minut. ### „Regresi 0.32.10 způsobil Vulkan" — na nás nesedí [Rozbor na dev.to](https://dev.to/milkyway008/ollama-model-loads-time-out-after-the-03210-upgrade-the-load-mode-change-and-the-fix-25m) připisuje regresi Vulkanu na integrovaných GPU. Máme CUDA a diskrétní kartu. Náš log uvádí jiný spouštěč (`host memory pressure`), ale ústí do téhož `--load-mode none`. Že to není jen Vulkan, potvrzuje [#18373](https://github.com/ollama/ollama/issues/18373). ### „Leakuje jen externí kill" — ne Leak vznikne i když load zruší **sám ollama scheduler** (`Load failed: timed out waiting for llama-server to start: context canceled` po odpadnutí klienta). Jedno takové zrušení stálo 5,19 GiB. Nezáleží tedy na tom, kdo `llama-server` ukončí — záleží na tom, že byl ukončen uprostřed loadu. --- ## 6. Upstream — nahlášené a neopravené | Issue | Co říká | Stav | |---|---|---| | [#18373](https://github.com/ollama/ollama/issues/18373) | Regrese načítání: 0.33.3 load 2m34s vs. 0.23.4 28s, SSD 600 MB/s místo 3 GB/s. Explicitně „all models", hlášeno i na NVIDII. | otevřené, bez reakce maintainerů | | [#10104](https://github.com/ollama/ollama/issues/10104) | 200 GB RAM, 80 GB VRAM, ollama sama nasadí `--no-mmap` a load selže. | zavřené bez řešení | | [#10341](https://github.com/ollama/ollama/issues/10341) | gemma plní RAM navzdory volné VRAM, **na RTX 4060 Ti 16 GB** — stejná karta. | duplikát #10040 | | [#8654](https://github.com/ollama/ollama/issues/8654) | „Available memory check should be disabled when mmap is in use" | otevřené od 1/2025 | | [#4895](https://github.com/ollama/ollama/issues/4895) + [PR #6854](https://github.com/ollama/ollama/pull/6854) | Žádost o globální řízení mmapu. | PR nesloučen | Námitka uživatele, že by tohle muselo trápit spoustu lidí, byla správná — jen míří opačným směrem: problém je široce hlášený a upstream ho neřeší. --- ## 7. Drobnosti k opravě - `zabbix-agent` běží a míří na `zabbix.hell`, ale má `Hostname=Zabbix server` (defaultní hodnota) — stroj se nehlásí jako `nvidia`. - `llama-server` běží s `--log-verbosity 4`; journald kvůli tomu při incidentu žral 1,9 % CPU a journal je zaplevelený. - LibreChat `titleConvo: true` + `titleModel: "current_model"` posílá na týž model druhý souběžný požadavek (v logu `Title generation timeout`). - Balík `earlyoom` je ve stavu `rc` — zbývá `apt purge`, na disku jsou `/etc/default/earlyoom` a `/etc/default/earlyoom.bak-20260913`.