Kde se to používá? HF jsem viděl u LLM a třeba na x86 to nebylo vůbec rychlejší než třeba "float" varianta. Na druhou stranu jsou i LLM s bajtovými váhami (ale nevím, jak to funguje vevnitř).
Pro embeddings. Tam je AArch64 úplně super. Samozřejmě ne tak rychlý jako GPU, jenže GPU jsou v čmoudu drahé/nejsou k dispozici, takže si na to beru vždycky mašinu s AArch64 a pomalejší x86-64 nechám pro ostatní (asi s Windows :-). Taky se s tím dají přežít SW-only LLM s half-float (tedy záleží na tom, na co, ale někdy fakt není GPU k dispozici).
Mimo neuronové sítě se používá v grafice, ikdyž je fakt, že většinu toho desktopový SW počítá na GPU, kde ARM nejspíš nepoběží. ;) Na druhou stranu, hodí se to třeba na MCU, který bere obraz z kamery a potřebuje provést nějaké zpracování – rozsah 8bitového integeru se do half-floatu vleze bez potíží a navíc si program může dovolit používat výrazně větší dynamický rozsah bez toho, aby hrozilo přetečení celočíselného typu.
Další oblast je zpracování jiných signálů, například data ze senzorů – přesnost half-floatu by mohla postačovat například na zpracování dat z akcelerometru, senzoru osvětlení, …
Pak mě napadá zvuk. Ale převod z 16bitového floatu do 16bitového integeru vypadá dost bolestně…
to mi připomnělo, že s typem half float jsem se poprvé kdysi setkal v Cg a později v HLSL (jazyky pro psaní shaderů).
Já pro změnu v GLSL. Při výpočtech barev na GPU se half-floaty fakt hodí, protože barvy typicky není potřeba počítat přesně, narozdíl od transformací.
Vzhledem k tomu, že NEON, narozdíl¹ od x87, (předpokládám) provádí pro half-floaty jednodušší výpočty, to zrychlení se může hodit. Bylo by zajímavé řešit s NEONem renderování 3D objektu na MCU (bez GPU). Jako use-case si představuji třeba náhled modelu² před tiskem na 3D tiskárně.
¹ Na x87 se floaty počítají vždy 80bitově (tzn. ještě širší než double), na požadovanou délku se ořezávají až při ukládání. SIMD instrukce na x86 to už mají jinak. (Jestli to je implementováno opravdu na méně cyklů netuším.)
² Ikdyž, náhled se daleko snáz dělá ze STL(-like) souboru, ale k tisku je potřeba ho naslajsovat, typicky do G-code příkazů. Ty je už trošku problém vykreslit vystínované a přitom efektivně.
Článek tvrdí, že mantisa má 10 bitů (z toho je počáteční jednotka implicitní, předpokládám, takže vlastně 11 bitů) a přitom přesnost je dle článku 5–6 číslic. To se do mantisy nemá šanci vejít: Přesnost v číslicích spočítáme jako log₁₀ 2⁽¹⁺¹⁰⁾ ≈ 3.311. Takže přesnost je 3 „až 4“ číslice.
Hodnoty ve výpočtu:
Oprášil jsem svůj starý kód a upravil jsem ho na 16bit floaty. Ano, nejmenší hodnota mantisy je 0.0009765625, to je 1/(2^10). Takže přesnost je zhruba 3-4 cifry. Moje aplikace je k dispozici na webu: https://marekknapek.github.io/half/#?n=0x01
Já děkuji za pěkný článek. Je to další věc po Pokročilých assemblerech na FIT VUT, co mě nakopla k tomu si někdy důkladně(ji) pohrát s ARMem.
Za zmínku stojí také to, že ARMy umí používat rozšířený rozsah o hodnotu exponentu 31, která by jinak značila ±∞/NaN. Takže se dostáváme na hodnoty až ±131008.