Přeskočit na obsah
U sebe doma 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 mezi oběma jmenovateli vychází na pět desetimiliontin – to je náš přepočet z obou vzorců, v návrhu změny nestojí.

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-k3bailingmoe3. Jsou to jména architektur uvnitř llama.cpp, ne jména modelů; pole model_typeconfig.json je spojuje s konkrétními vahami. Qwen3.8-27B se hlásí jako qwen3_5, Qwen3.8-Flash-Next jako qwen4_expLing-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

    llama.cpp nechá některé velké vkládací tabulky na disku místo v operační paměti

    Projekt llama.cpp vydal 4. září 2026 verzi 0.4.0 s volbou --lazy-mode: vybraná vkládací tabulka zůstane v souboru na disku a program z ní čte řádky až ve chvíli, kdy je…

  2. U sebe doma

    Ollama 0.33.3 čte doporučené hodnoty vzorkování přímo ze souboru modelu

    Ollama do teď používala vlastní výchozí teplotu a top_p vždycky, když je nepřepsal Modelfile nebo požadavek. Verze 0.33.3 z 2. září 2026 se nejdřív podívá, co si o sobě…

  3. U sebe doma

    Hugging Face zveřejnil 207 WebGPU kernelů pro prohlížeč, loader k nim vyšel jako náhled

    Organizace webgpu-kernels na Hubu nese 207 výpočetních programů pro grafický čip pod licencí Apache 2.0 a balíček @huggingface/kernels je z prohlížeče stáhne a spustí.…

  4. U sebe doma

    Projekt llama.cpp přestal převádět pět vah Qwen3-TTS 0,6B na 16 bitů

    Sestavení b10760 mění převod pomocného souboru pro model Qwen3-TTS 0,6B. Pět vah zůstane ve 32 bitech, protože mezivýsledek o hodnotě kolem 145 tisíc překračoval limit…