Přeskočit na obsah
U sebe doma aktualizováno 14. 10. 2026 4 min čtení

llama.cpp počítal u sedmi architektur normalizaci jinak než jejich referenční kód

Vektory dotazů a klíčů v hybridní vrstvě Gated DeltaNet dělil llama.cpp odmocninou ořezanou zdola, kdežto knihovna, ke které se jejich referenční kód hlásí, k té odmocnině malé číslo přičítá. Oprava je od 6. září v sestavení b10829 a její autor u ní rovnou ukázal, že se na výstupu skoro neprojeví.

Notebook MacBook Pro s čipem M1 otevřený na stole
Druhé z obou měření dopadu běželo na notebooku Applu přes Metal. Snímek je ilustrační. Foto: DYVER, Wikimedia Commons (CC BY-SA 4.0)

Hybridní modely posledních dvou let nepočítají pozornost v každé vrstvě klasicky. Část vrstev v nich obstarává lineární pozornost s hradly, u Qwenu a několika dalších rodin konkrétně Gated DeltaNet. Vektory dotazů a klíčů se v ní před vlastním výpočtem normalizují na jednotkovou délku – a přesně v tomhle kroku se llama.cpp rozcházel s kódem, ke kterému se referenční implementace těch modelů hlásí. Návrh změny od Daniela Hana z projektu Unsloth to 6. září srovnal.

Epsilon jako dolní mez, nebo jako přídavek

Funkce ggml_l2_norm počítá v llama.cpp měřítko takhle:

const float scale = 1.0f/fmaxf(sqrtf(sum), eps);

Malé číslo eps tu slouží jako dolní mez jmenovatele, tedy jako pojistka proti dělení nulou. Knihovna flash-linear-attention, na kterou se implementace Qwen3-Next v transformers výslovně odvolává, dělá totéž jinak – epsilon přičítá pod odmocninu:

b_rstd = 1 / tl.sqrt(tl.sum(b_x * b_x) + eps)

Pro běžná data je rozdíl nepatrný. Qwen3.8-27B i Qwen3.8-Flash-Next mají v config.json hodnotu rms_norm_eps rovnou 10⁻⁶. Když je druhá mocnina délky vektoru rovna jedné, vybere si fmaxf vždycky odmocninu a epsilon se neuplatní vůbec, kdežto reference dělí číslem √(1 + 10⁻⁶). Rozdíl √(1 + 10⁻⁶) − 1 mezi oběma jmenovateli vychází na pět desetimiliontin.

Podstatný začne být rozdíl až u vektorů s velmi krátkou délkou. Tam llama.cpp dělí nejméně hodnotou 10⁻⁶, kdežto reference nejméně její odmocninou, tedy číslem tisíckrát větším. Údržbář projektu vystupující pod jménem CISC na to v rozpravě namítl, že epsilon má bránit dělení nulou, ne posouvat hodnotu, a že se tedy chová divně ta knihovna.

Sedm architektur a jedna nová funkce

Změna se dotkla sedmi rodin: qwen35, qwen35moe, qwen3next, qwen4exp, kimi-linear, kimi-k3 a bailingmoe3. Jsou to jména architektur uvnitř llama.cpp, ne jména modelů; pole model_type v config.json je spojuje s konkrétními vahami. Qwen3.8-27B se hlásí jako qwen3_5, Qwen3.8-Flash-Next jako qwen4_exp a Ling-3.0-flash od InclusionAI jako bailing_hybrid.

Na samotnou ggml_l2_norm přitom nikdo nesáhl – používá ji i RWKV 7, kterého se změna netýká. Místo toho přibyla v src/models/models.h nová funkce poskládaná ze dvou existujících operací: normalizace střední kvadratické hodnoty s epsilonem vyděleným počtem prvků vektoru, a za ní vynásobení převrácenou odmocninou téhož počtu. Vyjde z toho přesně referenční tvar.

Tady je jedna pikantnost. Přesně tenhle postup měly v září 2025 transformers, když do sebe přidávaly Qwen3-Next – a o tři dny později ho vyhodily a nahradily přímým vzorcem. Rozdíl je v tom, že epsilon nedělily počtem prvků: při délce hlavy 128, kterou oba jmenované modely mají, se tím pod odmocninu dostane 1,28 · 10⁻⁴ místo žádaného 10⁻⁶, tedy hodnota 128krát větší. Opravu tehdy poslal člen týmu Qwen.

Kolik se toho na výstupu změnilo

Autor návrhu k němu přiložil vlastní měření odchylky rozdělení pravděpodobností, a to pro dvě ramena: jedno s opravou, druhé kontrolní s jinou velikostí dávky. Vůči čemu se ta odchylka počítá, u tabulky nestojí. U Qwen3.8-Flash-Next v kvantizaci UD-IQ1_S vyšla průměrná odchylka s opravou 0,032120 proti 0,032690 u kontroly, u Qwen3.8-27B v Q4_K_M pak 0,001750 proti 0,001769. Shoda nejpravděpodobnějšího tokenu byla u prvního modelu s opravou o něco horší (93,435 % proti 93,646 %) a u druhého o něco lepší (98,412 % proti 98,347 %). Nezopakoval to nikdo jiný.

Druhé měření přidal do rozpravy uživatel vystupující jako ovidiu-morar. Pustil čtyři otázky postavené na smyšlené premise a pět kontrolních otázek s premisou pravdivou, ve dvou kvantizacích a na dvou sestaveních, na notebooku Applu přes Metal, s nulovou teplotou a jedním během na buňku. Z osmi buněk se smyšlenou premisou se jich pět posunulo k bezpečnějšímu chování, tři zůstaly a žádná se nezhoršila; odpovědi na pravdivé otázky se nepohnuly vůbec, včetně jedné chyby, kterou obě sestavení udělala shodně na stejný počet tokenů.

Na tom měření je zajímavější jeho oprava než výsledek. První verzi autor sám stáhl: porovnával hlavní větev o 31 revizí starší, než na jaké návrh stál, takže rozdíl mohla způsobit kterákoli změna mezi nimi. Přestavěl proto hlavní větev přesně na revizi, ze které návrh vychází, a měřil znovu.

Proč se to sloučilo, když je dopad v šumu

Jiný přispěvatel v rozpravě připomněl, že si téhož nesouladu všiml už při psaní podpory Qwen3-Next a že mu tehdy z měření vyšel jako zanedbatelný. Rozhodl argument, který s numerikou nesouvisí. Podle CISC se ta knihovna použila při trénování, takže i kdyby byl její tvar technicky nesprávný, je pro hotové váhy závazný. Georgi Gerganov k tomu napsal, že se kloní ke shodě s referenční implementací bez ohledu na to, jak malý ten numerický dopad je (obojí přeloženo).

Návrh čekal na sloučení šest dní a změnil osm souborů, 27 přidaných řádků proti patnácti odebraným. Kdo si llama.cpp staví ze zdrojů, má opravu v sestavení b10829 a novějších; b10826, které vyšlo šest minut před sloučením, ji ještě nemá.

Zdroje

Diskuse

Zatím tu nikdo nediskutuje. Můžete být první.

Napsat příspěvek

Diskutovat můžete i bez účtu. S registrací se ale příspěvek zveřejní hned a nemusíte pokaždé vyplňovat jméno. Účet už máte? Přihlaste se.

Nezveřejňujeme ho, slouží jen redakci.

Podporuje zápis Texy: **tučně**, *kurzíva*, odrážky, odkazy.

Dál k tématu

  1. U sebe doma

    Ollama pozastavila převod starších modelů, po kterém zabíraly na disku dvojnásobek

    Ollama 0.40 začala bez ohlášení přepisovat starší stažené modely do tvaru, který llama.cpp přečte bez záplat, a původní soubor nechávala vedle jako zálohu. Převedené…

  2. U sebe doma

    DGX Spark se 64 GB má poloviční paměť, ale stejnou propustnost 273 GB/s

    Nvidia nabízí DGX Spark se 64 GB od 23. října přes šest výrobců za 4 999 dolarů, o čtvrtinu dráž, než loni stála verze se 128 GB. Ta mezitím podražila na 6 950 dolarů.…

  3. U sebe doma

    Nejstahovanější převod modelu Clef do GGUF nemá rozhodovací hlavu

    Cloudflare zveřejnil 30. září rozhodovací modely Clef a Clef-Flash, které místo textu vracejí pravděpodobnosti voleb. Počítá je zvláštní hlava se 128 miliony parametrů.…

  4. U sebe doma

    Ternární Bonsai 2 vyšel v baleních, která přečte jen fork llama.cpp

    Prism ML vydal druhou generaci svého ternárního přebalení modelu Qwen3.8-27B: 5,95 GB proti 53,8 GB u souboru v F16. Oba zveřejněné soubory ale nesou typy tenzorů, které…